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>
This commit is contained in:
NIIBE Yutaka 2022-10-14 13:52:54 +09:00
parent 5f1ce6cef5
commit c51139f2bc
No known key found for this signature in database
GPG Key ID: 640114AF89DE6054
4 changed files with 172 additions and 44 deletions

View File

@ -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 --*/

View File

@ -3768,23 +3768,59 @@ get_client_info (gnupg_fd_t fd, struct peer_info_s *out)
}
/* Start serving client on STREAM. */
void
start_command_handler_ssh_stream (ctrl_t ctrl, estream_t stream)
{
gpg_error_t err;
int ret;
err = agent_copy_startup_env (ctrl);
if (err)
goto out;
/* We have to disable the estream buffering, because the estream
core doesn't know about secure memory. */
ret = es_setvbuf (stream, NULL, _IONBF, 0);
if (ret)
{
log_error ("failed to disable buffering on socket stream: %s\n",
strerror (errno));
goto out;
}
/* Main processing loop. */
while ( !ssh_request_process (ctrl, stream) )
{
/* Check whether we have reached EOF before trying to read
another request. */
int c;
c = es_fgetc (stream);
if (c == EOF)
break;
es_ungetc (c, stream);
}
/* Reset the daemon in case it has been used. */
agent_reset_daemon (ctrl);
out:
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 = NULL;
gpg_error_t err;
int ret;
estream_t stream_sock;
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;
@ -3793,42 +3829,12 @@ start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client)
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);
if (ret)
{
err = gpg_error_from_syserror ();
log_error ("failed to disable buffering "
"on socket stream: %s\n", gpg_strerror (err));
goto out;
strerror (errno));
return;
}
/* Main processing loop. */
while ( !ssh_request_process (ctrl, stream_sock) )
{
/* Check whether we have reached EOF before trying to read
another request. */
int c;
c = es_fgetc (stream_sock);
if (c == EOF)
break;
es_ungetc (c, stream_sock);
}
/* Reset the daemon in case it has been used. */
agent_reset_daemon (ctrl);
out:
if (stream_sock)
es_fclose (stream_sock);
start_command_handler_ssh_stream (ctrl, stream_sock);
}

View File

@ -140,6 +140,7 @@ enum cmd_and_opt_values
oSSHSupport,
oSSHFingerprintDigest,
oPuttySupport,
oWin32OpenSSHSupport,
oDisableScdaemon,
oDisableCheckOwnSocket,
oS2KCount,
@ -227,6 +228,13 @@ static gpgrt_opt_t opts[] = {
/* */ N_("enable putty support")
#else
/* */ "@"
#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", "@"),
@ -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*/

View File

@ -54,7 +54,7 @@ AC_INIT([mym4_package],[mym4_version],[https://bugs.gnupg.org])
# build-aux/speedo.mk, build-aux/getswdb.sh, and Makefile.am
AC_DEFINE_UNQUOTED(GNUPG_SWDB_TAG, "gnupg24", [swdb tag for this branch])
NEED_GPGRT_VERSION=1.41
NEED_GPGRT_VERSION=1.46
NEED_LIBGCRYPT_API=1
NEED_LIBGCRYPT_VERSION=1.9.1