116359Sasami/* 216359Sasami * Copyright (c) 2000-2002 Damien Miller. All rights reserved. 316359Sasami * 416359Sasami * Redistribution and use in source and binary forms, with or without 516359Sasami * modification, are permitted provided that the following conditions 630665Skato * are met: 716359Sasami * 1. Redistributions of source code must retain the above copyright 816359Sasami * notice, this list of conditions and the following disclaimer. 916359Sasami * 2. Redistributions in binary form must reproduce the above copyright 1016359Sasami * notice, this list of conditions and the following disclaimer in the 1116359Sasami * documentation and/or other materials provided with the distribution. 1216359Sasami * 1316359Sasami * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1416359Sasami * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1516359Sasami * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1616359Sasami * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1716359Sasami * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1816359Sasami * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1916359Sasami * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2016359Sasami * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2130665Skato * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2230665Skato * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2330665Skato */ 2425088Skato 2525571Skato/* 2625088Skato * This is a simple GNOME SSH passphrase grabber. To use it, set the 2725088Skato * environment variable SSH_ASKPASS to point to the location of 2827690Skato * gnome-ssh-askpass before calling "ssh-add < /dev/null". 2927690Skato * 3016359Sasami * There is only two run-time options: if you set the environment variable 3116359Sasami * "GNOME_SSH_ASKPASS_GRAB_SERVER=true" then gnome-ssh-askpass will grab 3216359Sasami * the X server. If you set "GNOME_SSH_ASKPASS_GRAB_POINTER=true", then the 3316359Sasami * pointer will be grabbed too. These may have some benefit to security if 3416359Sasami * you don't trust your X server. We grab the keyboard always. 3516359Sasami */ 3616359Sasami 3716359Sasami/* 3816359Sasami * Compile with: 3918846Sasami * 4016359Sasami * cc `gnome-config --cflags gnome gnomeui` \ 4116359Sasami * gnome-ssh-askpass1.c -o gnome-ssh-askpass \ 4216359Sasami * `gnome-config --libs gnome gnomeui` 4316359Sasami * 4416359Sasami */ 4516359Sasami 4625256Skato#include <stdlib.h> 4716359Sasami#include <stdio.h> 4816359Sasami#include <string.h> 4927101Skato#include <gnome.h> 5020494Skato#include <X11/Xlib.h> 5127101Skato#include <gdk/gdkx.h> 5220494Skato 5320494Skatovoid 5420494Skatoreport_failed_grab (void) 5520494Skato{ 5620494Skato GtkWidget *err; 5716359Sasami 5816359Sasami err = gnome_message_box_new("Could not grab keyboard or mouse.\n" 5916359Sasami "A malicious client may be eavesdropping on your session.", 6016359Sasami GNOME_MESSAGE_BOX_ERROR, "EXIT", NULL); 6116359Sasami gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER); 6216359Sasami gtk_object_set(GTK_OBJECT(err), "type", GTK_WINDOW_POPUP, NULL); 6316359Sasami 6416359Sasami gnome_dialog_run_and_close(GNOME_DIALOG(err)); 6516359Sasami} 6616359Sasami 6726058Skatoint 6826058Skatopassphrase_dialog(char *message) 6926058Skato{ 7026058Skato char *passphrase; 7126058Skato char **messages; 7224112Skato int result, i, grab_server, grab_pointer; 7316359Sasami GtkWidget *dialog, *entry, *label; 7416359Sasami 7516359Sasami grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL); 7616359Sasami grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL); 7725088Skato 7825088Skato dialog = gnome_dialog_new("OpenSSH", GNOME_STOCK_BUTTON_OK, 7926058Skato GNOME_STOCK_BUTTON_CANCEL, NULL); 8025088Skato 8116359Sasami messages = g_strsplit(message, "\\n", 0); 8216359Sasami if (messages) 8316359Sasami for(i = 0; messages[i]; i++) { 8425088Skato label = gtk_label_new(messages[i]); 8525571Skato gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox), 8626058Skato label, FALSE, FALSE, 0); 8725571Skato } 8825571Skato 8925571Skato entry = gtk_entry_new(); 9025571Skato gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox), entry, FALSE, 9125571Skato FALSE, 0); 9225088Skato gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); 9326058Skato gtk_widget_grab_focus(entry); 9426058Skato 9526058Skato /* Center window and prepare for grab */ 9626058Skato gtk_object_set(GTK_OBJECT(dialog), "type", GTK_WINDOW_POPUP, NULL); 9725088Skato gnome_dialog_set_default(GNOME_DIALOG(dialog), 0); 9825088Skato gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); 9916359Sasami gtk_window_set_policy(GTK_WINDOW(dialog), FALSE, FALSE, TRUE); 10016359Sasami gnome_dialog_close_hides(GNOME_DIALOG(dialog), TRUE); 10116359Sasami gtk_container_set_border_width(GTK_CONTAINER(GNOME_DIALOG(dialog)->vbox), 10216359Sasami GNOME_PAD); 10316359Sasami gtk_widget_show_all(dialog); 10416359Sasami 10516359Sasami /* Grab focus */ 10616359Sasami if (grab_server) 10716359Sasami XGrabServer(GDK_DISPLAY()); 10816359Sasami if (grab_pointer && gdk_pointer_grab(dialog->window, TRUE, 0, 10916359Sasami NULL, NULL, GDK_CURRENT_TIME)) 11016359Sasami goto nograb; 11116359Sasami if (gdk_keyboard_grab(dialog->window, FALSE, GDK_CURRENT_TIME)) 11216359Sasami goto nograbkb; 11326058Skato 11426058Skato /* Make <enter> close dialog */ 11516359Sasami gnome_dialog_editable_enters(GNOME_DIALOG(dialog), GTK_EDITABLE(entry)); 11616359Sasami 11716359Sasami /* Run dialog */ 11816359Sasami result = gnome_dialog_run(GNOME_DIALOG(dialog)); 11924112Skato 12016359Sasami /* Ungrab */ 12116359Sasami if (grab_server) 12216359Sasami XUngrabServer(GDK_DISPLAY()); 12316359Sasami if (grab_pointer) 12416359Sasami gdk_pointer_ungrab(GDK_CURRENT_TIME); 12516359Sasami gdk_keyboard_ungrab(GDK_CURRENT_TIME); 12616359Sasami gdk_flush(); 12716359Sasami 12816359Sasami /* Report passphrase if user selected OK */ 12916359Sasami passphrase = gtk_entry_get_text(GTK_ENTRY(entry)); 13016359Sasami if (result == 0) 13124112Skato puts(passphrase); 13216359Sasami 13316359Sasami /* Zero passphrase in memory */ 13426058Skato memset(passphrase, '\0', strlen(passphrase)); 13525088Skato gtk_entry_set_text(GTK_ENTRY(entry), passphrase); 13625088Skato 13726058Skato gnome_dialog_close(GNOME_DIALOG(dialog)); 13825088Skato return (result == 0 ? 0 : -1); 13925088Skato 14026058Skato /* At least one grab failed - ungrab what we got, and report 14126058Skato the failure to the user. Note that XGrabServer() cannot 14226058Skato fail. */ 14326058Skato nograbkb: 14426058Skato gdk_pointer_ungrab(GDK_CURRENT_TIME); 14526058Skato nograb: 14626058Skato if (grab_server) 14726058Skato XUngrabServer(GDK_DISPLAY()); 14826058Skato gnome_dialog_close(GNOME_DIALOG(dialog)); 14916359Sasami 15016359Sasami report_failed_grab(); 15116359Sasami return (-1); 15216359Sasami} 15316359Sasami 15416359Sasamiint 15516359Sasamimain(int argc, char **argv) 15616359Sasami{ 15716359Sasami char *message; 15816359Sasami int result; 15916359Sasami 16016359Sasami gnome_init("GNOME ssh-askpass", "0.1", argc, argv); 16116359Sasami 16216359Sasami if (argc == 2) 16316359Sasami message = argv[1]; 16416359Sasami else 16516359Sasami message = "Enter your OpenSSH passphrase:"; 16616359Sasami 16716359Sasami setvbuf(stdout, 0, _IONBF, 0); 16816359Sasami result = passphrase_dialog(message); 16916359Sasami 17016359Sasami return (result); 17130330Skato} 17216359Sasami