diff --git a/agent/ChangeLog b/agent/ChangeLog index 4a0077507..a6885ea34 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,11 @@ +2007-06-18 Werner Koch + + * command.c (cmd_killagent) [W32]: New. + (cmd_getinfo): New. + * gpg-agent.c (get_agent_ssh_socket_name): New. + + * Makefile.am (gpg_agent_res_ldflags): Pass windows option to ld. + 2007-06-14 Werner Koch * protect-tool.c (main): Setup default socket name for diff --git a/agent/Makefile.am b/agent/Makefile.am index 34883ba20..1a8047856 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -60,7 +60,7 @@ if HAVE_W32_SYSTEM $(WINDRES) `echo $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) | \ sed -e 's/-I/--include-dir /g;s/-D/--define /g'` -i $< -o $@ -gpg_agent_res_ldflags = -Wl,gpg-agent-resource.o +gpg_agent_res_ldflags = -Wl,gpg-agent-resource.o -Wl,--subsystem,windows gpg_agent_res_deps = gpg-agent-resource.o else gpg_agent_res_ldflags = diff --git a/agent/agent.h b/agent/agent.h index b0d27823c..cb1cca084 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -191,6 +191,7 @@ cache_mode_t; /*-- gpg-agent.c --*/ void agent_exit (int rc) JNLIB_GCC_A_NR; /* Also implemented in other tools */ const char *get_agent_socket_name (void); +const char *get_agent_ssh_socket_name (void); /*-- command.c --*/ gpg_error_t agent_write_status (ctrl_t ctrl, const char *keyword, ...); diff --git a/agent/command.c b/agent/command.c index 8f1f126ed..011ed580d 100644 --- a/agent/command.c +++ b/agent/command.c @@ -58,6 +58,10 @@ struct server_local_s char *keydesc; /* Allocated description for the next key operation. */ int pause_io_logging; /* Used to suppress I/O logging during a command */ +#ifdef HAVE_W32_SYSTEM + int stopme; /* If set to true the agent will be terminated after + the end of this session. */ +#endif }; @@ -1306,6 +1310,67 @@ cmd_updatestartuptty (assuan_context_t ctx, char *line) } + +#ifdef HAVE_W32_SYSTEM +/* KILLAGENT + + Under Windows we start the agent on the fly. Thus it also make + sense to allow a client to stop the agent. */ +static int +cmd_killagent (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + ctrl->server_local->stopme = 1; + return 0; +} +#endif /*HAVE_W32_SYSTEM*/ + + + +/* GETINFO + + Multipurpose function to return a variety of information. + Supported values for WHAT are: + + version - Return the version of the program. + socket_name - Return the name of the socket. + ssh_socket_name - Return the name of the ssh socket. + + */ +static int +cmd_getinfo (assuan_context_t ctx, char *line) +{ + int rc = 0; + + if (!strcmp (line, "version")) + { + const char *s = VERSION; + rc = assuan_send_data (ctx, s, strlen (s)); + } + else if (!strcmp (line, "socket_name")) + { + const char *s = get_agent_socket_name (); + + if (s) + rc = assuan_send_data (ctx, s, strlen (s)); + else + rc = gpg_error (GPG_ERR_NO_DATA); + } + else if (!strcmp (line, "ssh_socket_name")) + { + const char *s = get_agent_ssh_socket_name (); + + if (s) + rc = assuan_send_data (ctx, s, strlen (s)); + else + rc = gpg_error (GPG_ERR_NO_DATA); + } + else + rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT"); + return rc; +} + + static int option_handler (assuan_context_t ctx, const char *key, const char *value) @@ -1439,6 +1504,10 @@ register_commands (assuan_context_t ctx) { "GETVAL", cmd_getval }, { "PUTVAL", cmd_putval }, { "UPDATESTARTUPTTY", cmd_updatestartuptty }, +#ifdef HAVE_W32_SYSTEM + { "KILLAGENT", cmd_killagent }, +#endif + { "GETINFO", cmd_getinfo }, { NULL } }; int i, rc; @@ -1542,6 +1611,10 @@ start_command_handler (ctrl_t ctrl, int listen_fd, int fd) /* Cleanup. */ assuan_deinit_server (ctx); +#ifdef HAVE_W32_SYSTEM + if (ctrl->server_local->stopme) + agent_exit (0); +#endif xfree (ctrl->server_local); ctrl->server_local = NULL; } diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index ae878eb86..0e6381972 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -1162,6 +1162,16 @@ get_agent_socket_name (void) return (s && *s)? s : NULL; } +/* Return the file name of the socket we are using for SSH + requests. */ +const char * +get_agent_ssh_socket_name (void) +{ + const char *s = socket_name_ssh; + + return (s && *s)? s : NULL; +} + /* Create a name for the socket. With USE_STANDARD_SOCKET given as diff --git a/agent/w32main.c b/agent/w32main.c new file mode 100644 index 000000000..5fccb7ea2 --- /dev/null +++ b/agent/w32main.c @@ -0,0 +1,178 @@ +/* w32main.c - W32 main entry pint and taskbar support for the GnuPG Agent + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#ifndef HAVE_W32_SYSTEM +#error This module is only useful for the W32 version of gpg-agent +#endif + +#include +#include +#include +#include + +#include "util.h" +#include "w32main.h" + +/* The instance handle has received by WinMain. */ +static HINSTANCE glob_hinst; +static HWND glob_hwnd; + + +/* Our window message processing function. */ +static LRESULT CALLBACK +wndw_proc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + + switch (msg) + { + case WM_USER: + fprintf (stderr,"%s: received WM_%s\n", __func__, "USER" ); + break; + + } + + return DefWindowProc (hwnd, msg, wparam, lparam); +} + + +/* This function is called to do some fast event polling and + processing. */ +void +w32_poll_events (void) +{ +/* MSG msg; */ + +/* fprintf (stderr,"%s: enter\n", __func__); */ +/* while (PeekMessage (&msg, glob_hwnd, 0, 0, PM_REMOVE)) */ +/* { */ +/* DispatchMessage (&msg); */ +/* } */ +/* fprintf (stderr,"%s: leave\n", __func__); */ +} + + + +static void * +handle_taskbar (void *ctx) +{ + WNDCLASS wndwclass = {0, wndw_proc, 0, 0, glob_hinst, + 0, 0, 0, 0, "gpg-agent"}; + NOTIFYICONDATA nid; + HWND hwnd; + MSG msg; + int rc; + + if (!RegisterClass (&wndwclass)) + { + log_error ("error registering window class\n"); + ExitThread (0); + } + hwnd = CreateWindow ("gpg-agent", "gpg-agent", + 0, 0, 0, 0, 0, + NULL, NULL, glob_hinst, NULL); + if (!hwnd) + { + log_error ("error creating main window\n"); + ExitThread (0); + } + glob_hwnd = hwnd; + UpdateWindow (hwnd); + + memset (&nid, 0, sizeof nid); + nid.cbSize = sizeof (nid); + nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; + nid.uCallbackMessage = WM_USER; + nid.hWnd = glob_hwnd; + nid.uID = 1; + nid.hIcon = LoadIcon (glob_hinst, MAKEINTRESOURCE (1)); + mem2str (nid.szTip, "GnuPG Agent version "PACKAGE_VERSION, + sizeof nid.szTip); + Shell_NotifyIcon (NIM_ADD, &nid); + DestroyIcon (nid.hIcon); + + fprintf (stderr, "%s: enter\n", __func__); + while ( (rc=GetMessage (&msg, hwnd, 0, 0)) ) + { + if (rc == -1) + { + log_error ("getMessage failed: %s\n", w32_strerror (-1)); + break; + } + TranslateMessage (&msg); + DispatchMessage (&msg); + } + fprintf (stderr,"%s: leave\n", __func__); + ExitThread (0); + return NULL; +} + + + +/* This function initializes the Window system and sets up the taskbar + icon. We only have very limited GUI support just to give the + taskbar icon a little bit of life. This fucntion is called once to + fire up the icon. */ +int +w32_setup_taskbar (void) +{ + SECURITY_ATTRIBUTES sa; + DWORD tid; + HANDLE th; + + memset (&sa, 0, sizeof sa); + sa.nLength = sizeof sa; + sa.bInheritHandle = FALSE; + + fprintf (stderr,"creating thread for the taskbar_event_loop...\n"); + th = CreateThread (&sa, 128*1024, + (LPTHREAD_START_ROUTINE)handle_taskbar, + NULL, 0, &tid); + fprintf (stderr,"created thread %p tid=%d\n", th, (int)tid); + + CloseHandle (th); + + return 0; +} + + +/* The main entry point for the Windows version. We save away all GUI + related stuff, parse the commandline and finally call the real + main. */ +int WINAPI +WinMain (HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int showcmd) +{ + /* Fixme: We need a parser for the command line. Should be + available in some CRT code - need to see whether we can find a + GNU version. For nopw we call gpg-agent with a couple of fixed arguments + */ + char *argv[] = { "gpg-agent.exe", "--daemon", "-v", "--debug-all", NULL }; + + + glob_hinst = hinst; + + return w32_main (DIM(argv)-1, argv); +} + + + + + diff --git a/agent/w32main.h b/agent/w32main.h new file mode 100644 index 000000000..c1b3f7d70 --- /dev/null +++ b/agent/w32main.h @@ -0,0 +1,34 @@ +/* w32main.h - W32 main entry point and support functions + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#ifndef AGENT_W32MAIN_H +#define AGENT_W32MAIN_H + +/* This is the actual entry point as called by w32main.c. */ +int w32_main (int argc, char **argv ); + +/* Fire up the icon for the taskbar. */ +int w32_setup_taskbar (void); + +void w32_poll_events (void); + + +#endif /*AGENT_W32MAIN_H*/ diff --git a/doc/ChangeLog b/doc/ChangeLog index 9dfcb86b4..df1b7d82f 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2007-06-18 Werner Koch + + * gpg-agent.texi (Agent GETINFO): New. + 2007-06-06 Werner Koch * Makefile.am (yat2m): Use a plain rule to build it for the sake diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index ed3ff6052..3f0412538 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -674,6 +674,7 @@ secret keys. * Agent PASSWD:: Change a Passphrase * Agent UPDATESTARTUPTTY:: Change the Standard Display * Agent GETEVENTCOUNTER:: Get the Event Counters +* Agent GETINFO:: Return information about the process @end menu @node Agent PKDECRYPT @@ -1121,6 +1122,26 @@ Incremented for added or removed private keys. Incremented for changes of the card readers stati. @end table +@node Agent GETINFO +@subsection Return information about the process + +This is a multipurpose function to return a variety of information. + +@example +GETINFO @var{what} +@end example + +The value of @var{what} specifies the kind of information returned: +@table @code +@item version +Return the version of the program. +@item socket_name +Return the name of the socket used to connect the agent. +@item ssh_socket_name +Return the name of the socket used for SSH connections. If SSH support +has not been enabled the error @code{GPG_ERR_NO_DATA} will be returned. +@end table + @mansect see also @ifset isman