diff options
author | NIIBE Yutaka <gniibe@fsij.org> | 2022-10-14 06:52:54 +0200 |
---|---|---|
committer | NIIBE Yutaka <gniibe@fsij.org> | 2022-10-14 06:52:54 +0200 |
commit | c51139f2bc546c6bd4548e24a604f2178a2b8366 (patch) | |
tree | 050da49953c5bbce3b66f478e45ba24b4184a082 /agent | |
parent | common: Don't use FD2INT for POSIX-only code. (diff) | |
download | gnupg2-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.h | 1 | ||||
-rw-r--r-- | agent/command-ssh.c | 70 | ||||
-rw-r--r-- | agent/gpg-agent.c | 127 |
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*/ |