summaryrefslogtreecommitdiffstats
path: root/agent
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2022-10-14 06:52:54 +0200
committerNIIBE Yutaka <gniibe@fsij.org>2022-10-14 06:52:54 +0200
commitc51139f2bc546c6bd4548e24a604f2178a2b8366 (patch)
tree050da49953c5bbce3b66f478e45ba24b4184a082 /agent
parentcommon: Don't use FD2INT for POSIX-only code. (diff)
downloadgnupg2-c51139f2bc546c6bd4548e24a604f2178a2b8366.tar.xz
gnupg2-c51139f2bc546c6bd4548e24a604f2178a2b8366.zip
agent,w32: Support Win32-OpenSSH emulation by gpg-agent.
* agent/agent.h (start_command_handler_ssh_stream): New. * agent/command-ssh.c (start_command_handler_ssh_stream): New. * agent/gpg-agent.c (oWin32OpenSSHSupport): New. (W32_DEFAILT_AGENT_PIPE_NAME): New. (main): Add oWin32OpenSSHSupport support. (win32_openssh_thread): New. (handle_connections): Spawn win32_openssh_thread. * configure.ac (NEED_GPGRT_VERSION): Require libgpg-error 1.46. -- GnuPG-bug-id: 3883 Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
Diffstat (limited to 'agent')
-rw-r--r--agent/agent.h1
-rw-r--r--agent/command-ssh.c70
-rw-r--r--agent/gpg-agent.c127
3 files changed, 163 insertions, 35 deletions
diff --git a/agent/agent.h b/agent/agent.h
index 30f30200d..ee5c67568 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -453,6 +453,7 @@ gpg_error_t ssh_search_control_file (ssh_control_file_t cf,
int *r_disabled,
int *r_ttl, int *r_confirm);
+void start_command_handler_ssh_stream (ctrl_t ctrl, estream_t stream);
void start_command_handler_ssh (ctrl_t, gnupg_fd_t);
/*-- findkey.c --*/
diff --git a/agent/command-ssh.c b/agent/command-ssh.c
index ce2b5df9d..50622850c 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -3768,67 +3768,73 @@ get_client_info (gnupg_fd_t fd, struct peer_info_s *out)
}
-/* Start serving client on SOCK_CLIENT. */
+/* Start serving client on STREAM. */
void
-start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client)
+start_command_handler_ssh_stream (ctrl_t ctrl, estream_t stream)
{
- estream_t stream_sock = NULL;
gpg_error_t err;
int ret;
- struct peer_info_s peer_info;
- es_syshd_t syshd;
-
- syshd.type = ES_SYSHD_SOCK;
- syshd.u.sock = sock_client;
err = agent_copy_startup_env (ctrl);
if (err)
goto out;
- get_client_info (sock_client, &peer_info);
- ctrl->client_pid = peer_info.pid;
- ctrl->client_uid = peer_info.uid;
-
- /* Create stream from socket. */
- stream_sock = es_sysopen (&syshd, "r+");
- if (!stream_sock)
- {
- err = gpg_error_from_syserror ();
- log_error (_("failed to create stream from socket: %s\n"),
- gpg_strerror (err));
- goto out;
- }
/* We have to disable the estream buffering, because the estream
core doesn't know about secure memory. */
- ret = es_setvbuf (stream_sock, NULL, _IONBF, 0);
+ ret = es_setvbuf (stream, NULL, _IONBF, 0);
if (ret)
{
- err = gpg_error_from_syserror ();
- log_error ("failed to disable buffering "
- "on socket stream: %s\n", gpg_strerror (err));
+ log_error ("failed to disable buffering on socket stream: %s\n",
+ strerror (errno));
goto out;
}
/* Main processing loop. */
- while ( !ssh_request_process (ctrl, stream_sock) )
+ while ( !ssh_request_process (ctrl, stream) )
{
/* Check whether we have reached EOF before trying to read
- another request. */
+ another request. */
int c;
- c = es_fgetc (stream_sock);
+ c = es_fgetc (stream);
if (c == EOF)
break;
- es_ungetc (c, stream_sock);
+ es_ungetc (c, stream);
}
/* Reset the daemon in case it has been used. */
agent_reset_daemon (ctrl);
-
out:
- if (stream_sock)
- es_fclose (stream_sock);
+ es_fclose (stream);
+}
+
+
+/* Start serving client on SOCK_CLIENT. */
+void
+start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client)
+{
+ estream_t stream_sock;
+ struct peer_info_s peer_info;
+ es_syshd_t syshd;
+
+ syshd.type = ES_SYSHD_SOCK;
+ syshd.u.sock = sock_client;
+
+ get_client_info (sock_client, &peer_info);
+ ctrl->client_pid = peer_info.pid;
+ ctrl->client_uid = peer_info.uid;
+
+ /* Create stream from socket. */
+ stream_sock = es_sysopen (&syshd, "r+");
+ if (!stream_sock)
+ {
+ log_error (_("failed to create stream from socket: %s\n"),
+ strerror (errno));
+ return;
+ }
+
+ start_command_handler_ssh_stream (ctrl, stream_sock);
}
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index fad2a363e..412eb43e1 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -140,6 +140,7 @@ enum cmd_and_opt_values
oSSHSupport,
oSSHFingerprintDigest,
oPuttySupport,
+ oWin32OpenSSHSupport,
oDisableScdaemon,
oDisableCheckOwnSocket,
oS2KCount,
@@ -229,6 +230,13 @@ static gpgrt_opt_t opts[] = {
/* */ "@"
#endif
),
+ ARGPARSE_o_s (oWin32OpenSSHSupport, "enable-win32-openssh-support",
+#ifdef HAVE_W32_SYSTEM
+ /* */ N_("enable Win32-OpenSSH support")
+#else
+ /* */ "@"
+#endif
+ ),
ARGPARSE_s_n (oDisableExtendedKeyFormat, "disable-extended-key-format", "@"),
ARGPARSE_s_n (oEnableExtendedKeyFormat, "enable-extended-key-format", "@"),
ARGPARSE_s_i (oListenBacklog, "listen-backlog", "@"),
@@ -357,6 +365,10 @@ static int putty_support;
value. Putty currently (0.62) uses 8k, thus 16k should be enough
for the foreseeable future. */
#define PUTTY_IPC_MAXLEN 16384
+
+/* Path to the pipe, which handles requests from Win32-OpenSSH. */
+static const char *win32_openssh_support;
+#define W32_DEFAILT_AGENT_PIPE_NAME "\\\\.\\pipe\\openssh-ssh-agent"
#endif /*HAVE_W32_SYSTEM*/
/* The list of open file descriptors at startup. Note that this list
@@ -1289,6 +1301,15 @@ main (int argc, char **argv)
# endif
break;
+ case oWin32OpenSSHSupport:
+# ifdef HAVE_W32_SYSTEM
+ if (pargs.r_type)
+ win32_openssh_support = pargs.r.ret_str;
+ else
+ win32_openssh_support = W32_DEFAILT_AGENT_PIPE_NAME;
+# endif
+ break;
+
case oExtraSocket:
opt.extra_socket = 1; /* (1 = points into argv) */
socket_name_extra = pargs.r.ret_str;
@@ -2756,6 +2777,99 @@ putty_message_thread (void *arg)
log_info ("putty message loop thread stopped\n");
return NULL;
}
+
+#define BUFSIZE (5 * 1024)
+
+/* The thread handling Win32-OpenSSH requests through NamedPipe. */
+static void *
+win32_openssh_thread (void *arg)
+{
+ HANDLE pipe;
+
+ (void)arg;
+
+ if (opt.verbose)
+ log_info ("Win32-OpenSSH thread started\n");
+
+ while (1)
+ {
+ ctrl_t ctrl = NULL;
+ estream_t ssh_stream = NULL;
+ es_syshd_t syshd;
+
+ npth_unprotect ();
+ pipe = CreateNamedPipeA (win32_openssh_support, PIPE_ACCESS_DUPLEX,
+ (PIPE_TYPE_BYTE | PIPE_READMODE_BYTE
+ | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS),
+ PIPE_UNLIMITED_INSTANCES,
+ BUFSIZE, BUFSIZE, 0, NULL);
+
+ if (pipe == INVALID_HANDLE_VALUE)
+ {
+ npth_protect ();
+ log_error ("cannot create pipe: %ld\n", GetLastError ());
+ break;
+ }
+
+ if (ConnectNamedPipe (pipe, NULL) == 0)
+ {
+ npth_protect ();
+ CloseHandle (pipe);
+ log_error ("Error at ConnectNamedPipe: %ld\n", GetLastError ());
+ break;
+ }
+
+ npth_protect ();
+ ctrl = xtrycalloc (1, sizeof *ctrl);
+ if (!ctrl)
+ {
+ CloseHandle (pipe);
+ log_error ("error allocating connection control data: %s\n",
+ strerror (errno));
+ break;
+ }
+
+#if _WIN32_WINNT >= 0x600
+ if (!GetNamedPipeClientProcessId (pipe, &ctrl->client_pid))
+ log_info ("failed to get client process id: %ld\n", GetLastError ());
+ else
+ ctrl->client_uid = -1;
+#endif
+
+ ctrl->session_env = session_env_new ();
+ if (!ctrl->session_env)
+ {
+ log_error ("error allocating session environment block: %s\n",
+ strerror (errno));
+ agent_deinit_default_ctrl (ctrl);
+ xfree (ctrl);
+ CloseHandle (pipe);
+ break;
+ }
+ agent_init_default_ctrl (ctrl);
+
+ syshd.type = ES_SYSHD_HANDLE;
+ syshd.u.handle = pipe;
+ ssh_stream = es_sysopen (&syshd, "r+b");
+ if (!ssh_stream)
+ {
+ agent_deinit_default_ctrl (ctrl);
+ xfree (ctrl);
+ CloseHandle (pipe);
+ break;
+ }
+
+ start_command_handler_ssh_stream (ctrl, ssh_stream);
+
+ agent_deinit_default_ctrl (ctrl);
+ xfree (ctrl);
+ CloseHandle (pipe);
+ }
+
+ if (opt.verbose)
+ log_info ("Win32-OpenSSH thread stopped\n");
+ return NULL;
+}
#endif /*HAVE_W32_SYSTEM*/
@@ -2948,9 +3062,16 @@ handle_connections (gnupg_fd_t listen_fd,
ret = npth_create (&thread, &tattr, putty_message_thread, NULL);
if (ret)
- {
- log_error ("error spawning putty message loop: %s\n", strerror (ret));
- }
+ log_error ("error spawning putty message loop: %s\n", strerror (ret));
+ }
+
+ if (win32_openssh_support)
+ {
+ npth_t thread;
+
+ ret = npth_create (&thread, &tattr, win32_openssh_thread, NULL);
+ if (ret)
+ log_error ("error spawning Win32-OpenSSH loop: %s\n", strerror (ret));
}
#endif /*HAVE_W32_SYSTEM*/