| /* |
| * Copyright (c) 2000-2001 Damien Miller. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /* |
| * This is a simple GNOME SSH passphrase grabber. To use it, set the |
| * environment variable SSH_ASKPASS to point to the location of |
| * gnome-ssh-askpass before calling "ssh-add < /dev/null". |
| * |
| * There is only one run-time option: if you set the environment variable |
| * "GNOME_SSH_ASKPASS_NOGRAB=true" then gnome-ssh-askpass will not grab |
| * the X server. I have found this necessary to avoid server hangs with |
| * X input extensions (e.g. kinput2) enabled. - djm |
| */ |
| |
| /* |
| * Compile with: |
| * |
| * cc `gnome-config --cflags gnome gnomeui` \ |
| * gnome-ssh-askpass.c -o gnome-ssh-askpass \ |
| * `gnome-config --libs gnome gnomeui` |
| * |
| */ |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <gnome.h> |
| #include <X11/Xlib.h> |
| #include <gdk/gdkx.h> |
| |
| void |
| report_failed_grab (void) |
| { |
| GtkWidget *err; |
| |
| err = gnome_message_box_new("Could not grab keyboard or mouse.\n" |
| "A malicious client may be eavesdropping on your session.", |
| GNOME_MESSAGE_BOX_ERROR, "EXIT", NULL); |
| gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER); |
| gtk_object_set(GTK_OBJECT(err), "type", GTK_WINDOW_POPUP, NULL); |
| |
| gnome_dialog_run_and_close(GNOME_DIALOG(err)); |
| } |
| |
| void |
| passphrase_dialog(char *message) |
| { |
| char *passphrase; |
| char **messages; |
| int result, i, grab_server; |
| GtkWidget *dialog, *entry, *label; |
| |
| grab_server = (getenv("GNOME_SSH_ASKPASS_NOGRAB") == NULL); |
| |
| dialog = gnome_dialog_new("OpenSSH", GNOME_STOCK_BUTTON_OK, |
| GNOME_STOCK_BUTTON_CANCEL, NULL); |
| |
| messages = g_strsplit(message, "\\n", 0); |
| if (messages) |
| for(i = 0; messages[i]; i++) { |
| label = gtk_label_new(messages[i]); |
| gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox), |
| label, FALSE, FALSE, 0); |
| } |
| |
| entry = gtk_entry_new(); |
| gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox), entry, FALSE, |
| FALSE, 0); |
| gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); |
| gtk_widget_grab_focus(entry); |
| |
| /* Center window and prepare for grab */ |
| gtk_object_set(GTK_OBJECT(dialog), "type", GTK_WINDOW_POPUP, NULL); |
| gnome_dialog_set_default(GNOME_DIALOG(dialog), 0); |
| gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); |
| gtk_window_set_policy(GTK_WINDOW(dialog), FALSE, FALSE, TRUE); |
| gnome_dialog_close_hides(GNOME_DIALOG(dialog), TRUE); |
| gtk_container_set_border_width(GTK_CONTAINER(GNOME_DIALOG(dialog)->vbox), |
| GNOME_PAD); |
| gtk_widget_show_all(dialog); |
| |
| /* Grab focus */ |
| if (grab_server) |
| XGrabServer(GDK_DISPLAY()); |
| if (gdk_pointer_grab(dialog->window, TRUE, 0, NULL, NULL, |
| GDK_CURRENT_TIME)) |
| goto nograb; |
| if (gdk_keyboard_grab(dialog->window, FALSE, GDK_CURRENT_TIME)) |
| goto nograbkb; |
| |
| /* Make <enter> close dialog */ |
| gnome_dialog_editable_enters(GNOME_DIALOG(dialog), GTK_EDITABLE(entry)); |
| |
| /* Run dialog */ |
| result = gnome_dialog_run(GNOME_DIALOG(dialog)); |
| |
| /* Ungrab */ |
| if (grab_server) |
| XUngrabServer(GDK_DISPLAY()); |
| gdk_pointer_ungrab(GDK_CURRENT_TIME); |
| gdk_keyboard_ungrab(GDK_CURRENT_TIME); |
| gdk_flush(); |
| |
| /* Report passphrase if user selected OK */ |
| passphrase = gtk_entry_get_text(GTK_ENTRY(entry)); |
| if (result == 0) |
| puts(passphrase); |
| |
| /* Zero passphrase in memory */ |
| memset(passphrase, '\0', strlen(passphrase)); |
| gtk_entry_set_text(GTK_ENTRY(entry), passphrase); |
| |
| gnome_dialog_close(GNOME_DIALOG(dialog)); |
| return; |
| |
| /* At least one grab failed - ungrab what we got, and report |
| the failure to the user. Note that XGrabServer() cannot |
| fail. */ |
| nograbkb: |
| gdk_pointer_ungrab(GDK_CURRENT_TIME); |
| nograb: |
| if (grab_server) |
| XUngrabServer(GDK_DISPLAY()); |
| gnome_dialog_close(GNOME_DIALOG(dialog)); |
| |
| report_failed_grab(); |
| } |
| |
| int |
| main(int argc, char **argv) |
| { |
| char *message; |
| |
| gnome_init("GNOME ssh-askpass", "0.1", argc, argv); |
| |
| if (argc == 2) |
| message = argv[1]; |
| else |
| message = "Enter your OpenSSH passphrase:"; |
| |
| setvbuf(stdout, 0, _IONBF, 0); |
| passphrase_dialog(message); |
| return 0; |
| } |