summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2022-11-04 19:04:39 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2022-11-04 19:04:39 +0900
commit870fdcf92e5991c0bb2e349a951aa8dd93b0e22f (patch)
treef90ab83f8b54e3db82888566562dcc9afa69daf1
parentce794a0a88a8dca11810ac79e6be6bf6b4e5326c (diff)
downloadlibassuan-870fdcf92e5991c0bb2e349a951aa8dd93b0e22f.tar.gz
w32: Support sendfd/recvfd through pipe connection.
* src/assuan-defs.h (w32_fdpass_send, w32_fdpass_recv): New. * src/assuan-pipe-connect.c [HAVE_W32_SYSTEM] (pipe_connect): Set w32_fdpass_send. [!HAVE_W32_SYSTEM] (assuan_pipe_connect): Use socketpair_connect. * src/assuan-pipe-server.c [HAVE_W32_SYSTEM] (assuan_init_pipe_server): Set w32_fdpass_recv. * src/system-w32.c (get_file_handle): New. (w32_fdpass_send): New, using "SENDFD" internal command. (w32_fdpass_recv): New, using the result of "SENDFD" internal command. -- GnuPG-bug-id: 6236 Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
-rw-r--r--src/assuan-defs.h2
-rw-r--r--src/assuan-pipe-connect.c16
-rw-r--r--src/assuan-pipe-server.c4
-rw-r--r--src/system-w32.c77
4 files changed, 91 insertions, 8 deletions
diff --git a/src/assuan-defs.h b/src/assuan-defs.h
index 47ff4ef..68bd983 100644
--- a/src/assuan-defs.h
+++ b/src/assuan-defs.h
@@ -327,6 +327,8 @@ int _assuan_error_is_eagain (assuan_context_t ctx, gpg_error_t err);
#ifdef HAVE_W32_SYSTEM
char *_assuan_w32_strerror (assuan_context_t ctx, int ec);
+gpg_error_t w32_fdpass_send (assuan_context_t ctx, assuan_fd_t fd);
+gpg_error_t w32_fdpass_recv (assuan_context_t ctx, assuan_fd_t *fd);
#endif /*HAVE_W32_SYSTEM*/
diff --git a/src/assuan-pipe-connect.c b/src/assuan-pipe-connect.c
index 1589d79..13ea3de 100644
--- a/src/assuan-pipe-connect.c
+++ b/src/assuan-pipe-connect.c
@@ -209,7 +209,11 @@ pipe_connect (assuan_context_t ctx,
ctx->engine.release = _assuan_client_release;
ctx->engine.readfnc = _assuan_simple_read;
ctx->engine.writefnc = _assuan_simple_write;
+#ifdef HAVE_W32_SYSTEM
+ ctx->engine.sendfd = w32_fdpass_send;
+#else
ctx->engine.sendfd = NULL;
+#endif
ctx->engine.receivefd = NULL;
ctx->finish_handler = _assuan_client_finish;
ctx->max_accepts = 1;
@@ -413,16 +417,12 @@ assuan_pipe_connect (assuan_context_t ctx,
TRACE2 (ctx, ASSUAN_LOG_CTX, "assuan_pipe_connect", ctx,
"name=%s, flags=0x%x", name ? name : "(null)", flags);
+#ifndef HAVE_W32_SYSTEM
if (flags & ASSUAN_PIPE_CONNECT_FDPASSING)
- {
-#ifdef HAVE_W32_SYSTEM
- return _assuan_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
-#else
- return socketpair_connect (ctx, name, argv, fd_child_list,
- atfork, atforkvalue);
-#endif
- }
+ return socketpair_connect (ctx, name, argv, fd_child_list,
+ atfork, atforkvalue);
else
+#endif
return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue,
flags);
}
diff --git a/src/assuan-pipe-server.c b/src/assuan-pipe-server.c
index db66978..8da54ad 100644
--- a/src/assuan-pipe-server.c
+++ b/src/assuan-pipe-server.c
@@ -115,7 +115,11 @@ assuan_init_pipe_server (assuan_context_t ctx, assuan_fd_t filedes[2])
ctx->engine.readfnc = _assuan_simple_read;
ctx->engine.writefnc = _assuan_simple_write;
ctx->engine.sendfd = NULL;
+#ifdef HAVE_W32_SYSTEM
+ ctx->engine.receivefd = w32_fdpass_recv;
+#else
ctx->engine.receivefd = NULL;
+#endif
ctx->max_accepts = 1;
s = getenv ("_assuan_pipe_connect_pid");
diff --git a/src/system-w32.c b/src/system-w32.c
index cfc1d61..76ff2a0 100644
--- a/src/system-w32.c
+++ b/src/system-w32.c
@@ -167,6 +167,83 @@ __assuan_close (assuan_context_t ctx, assuan_fd_t fd)
+/* Get a file HANDLE to send, from POSIX fd. */
+static gpg_error_t
+get_file_handle (int fd, int server_pid, HANDLE *r_handle)
+{
+ HANDLE prochandle, handle, newhandle;
+
+ handle = (void *)_get_osfhandle (fd);
+
+ prochandle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, server_pid);
+ if (!prochandle)
+ return gpg_error (GPG_ERR_ASS_PARAMETER);/*FIXME: error*/
+
+ if (!DuplicateHandle (GetCurrentProcess (), handle, prochandle, &newhandle,
+ 0, TRUE, DUPLICATE_SAME_ACCESS))
+ {
+ CloseHandle (prochandle);
+ return gpg_error (GPG_ERR_ASS_PARAMETER);/*FIXME: error*/
+ }
+ CloseHandle (prochandle);
+ *r_handle = newhandle;
+ return 0;
+}
+
+
+/* Send a FD (which means POSIX fd) to the peer. */
+gpg_error_t
+w32_fdpass_send (assuan_context_t ctx, assuan_fd_t fd)
+{
+ char fdpass_msg[256];
+ int res;
+ int fd0; /* POSIX fd */
+ intptr_t fd_converted_to_integer;
+ HANDLE file_handle;
+ gpg_error_t err;
+
+ fd_converted_to_integer = (intptr_t)fd;
+ fd0 = (int)fd_converted_to_integer; /* Bit pattern is possibly truncated. */
+
+ err = get_file_handle (fd0, ctx->pid, &file_handle);
+ if (err)
+ return err;
+
+ res = snprintf (fdpass_msg, sizeof (fdpass_msg), "SENDFD %p", file_handle);
+ if (res < 0)
+ {
+ CloseHandle (file_handle);
+ return gpg_error (GPG_ERR_ASS_PARAMETER);/*FIXME: error*/
+ }
+
+ err = assuan_transact (ctx, fdpass_msg, NULL, NULL, NULL, NULL, NULL, NULL);
+ return err;
+}
+
+
+/* Receive a HANDLE from the peer and turn it into a FD (POSIX fd). */
+gpg_error_t
+w32_fdpass_recv (assuan_context_t ctx, assuan_fd_t *fd)
+{
+ int i;
+
+ if (!ctx->uds.pendingfdscount)
+ {
+ TRACE0 (ctx, ASSUAN_LOG_SYSIO, "w32_receivefd", ctx,
+ "no pending file descriptors");
+ return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
+ }
+
+ *fd = ctx->uds.pendingfds[0];
+ for (i=1; i < ctx->uds.pendingfdscount; i++)
+ ctx->uds.pendingfds[i-1] = ctx->uds.pendingfds[i];
+ ctx->uds.pendingfdscount--;
+
+ TRACE1 (ctx, ASSUAN_LOG_SYSIO, "w32_fdpass_recv", ctx,
+ "received fd: %p", ctx->uds.pendingfds[0]);
+ return 0;
+}
+
ssize_t
__assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
{