96cf17b159
* configure.ac: Activate UIServer if FD passing is enabled and Assuan is available. m4/ 2009-11-10 Marcus Brinkmann <marcus@g10code.de> * libassuan.m4: Fix LIBASSUAN_VERSION. src/ 2009-11-10 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (uiserver_components): New variable. (main_sources): Add it. * ops.h, key.c (_gpgme_key_append_name): Take CONVERT argument, implement it. Adjust callers. (gpgme_key_from_uid): New function. * gpgme.h.in (gpgme_protocol_t): Add GPGME_PROTOCOL_DEFAULT. (gpgme_encrypt_flags_t): Add GPGME_ENCRYPT_PREPARE, GPGME_ENCRYPT_EXPECT_SIGN. (gpgme_set_sub_protocol, gpgme_key_from_uid): New functions. * libgpgme.vers, gpgme.def: Add new functions. * gpgme.c (gpgme_set_protocol): Add UIServer protocol. (gpgme_set_sub_protocol): New function. (gpgme_get_protocol_name): Add UIServer and default protocol. * assuan-support.c: Return correct error values, implement socketpair for POSIX. * priv-io.h, posix-io.c, w32-io.c, w32-glib-io.c, w32-qt-io.cpp (_gpgme_io_spawn): Add ATFORK and ATFORKVALUE arguments. Implement it for POSIX. Adjust all callers. * engine.h, engine-backend.h (_gpgme_engine_set_protocol) (_gpgme_engine_op_decrypt_verify): New prototypes. Adjust all users. * engine.c (engine_ops, gpgme_get_engine_info): Add UIServer engine. (_gpgme_engine_set_protocol, _gpgme_engine_op_decrypt_verify): New function. * decrypt-verify.c (decrypt_verify_start): Call _gpgme_engine_op_decrypt_verify. * util.h, posix-util.c, w32-util.c (_gpgme_get_uiserver_socket_path): New function. * engine-gpgsm.c (gpgsm_set_fd): Fix _gpgme_io_pipe invocation. * gpgme-tool.c: Some support for UIServer protocol. * engine-uiserver.c: New file.
230 lines
4.3 KiB
C
230 lines
4.3 KiB
C
#if HAVE_CONFIG_H
|
||
#include <config.h>
|
||
#endif
|
||
|
||
#include <assert.h>
|
||
#include <stdlib.h>
|
||
#include <errno.h>
|
||
|
||
#include "assuan.h"
|
||
|
||
#include "gpgme.h"
|
||
#include "ath.h"
|
||
#include "priv-io.h"
|
||
#include "debug.h"
|
||
|
||
|
||
struct assuan_malloc_hooks _gpgme_assuan_malloc_hooks =
|
||
{
|
||
malloc,
|
||
realloc,
|
||
free
|
||
};
|
||
|
||
|
||
int
|
||
_gpgme_assuan_log_cb (assuan_context_t ctx, void *hook,
|
||
unsigned int cat, const char *msg)
|
||
{
|
||
if (msg == NULL)
|
||
return 1;
|
||
|
||
_gpgme_debug (DEBUG_ASSUAN, "%s", msg);
|
||
return 0;
|
||
}
|
||
|
||
|
||
static void
|
||
my_usleep (assuan_context_t ctx, unsigned int usec)
|
||
{
|
||
/* FIXME: Add to ath. */
|
||
__assuan_usleep (ctx, usec);
|
||
}
|
||
|
||
/* Create a pipe with an inheritable end. */
|
||
static int
|
||
my_pipe (assuan_context_t ctx, assuan_fd_t fds[2], int inherit_idx)
|
||
{
|
||
return _gpgme_io_pipe (fds, inherit_idx);
|
||
}
|
||
|
||
|
||
/* Close the given file descriptor, created with _assuan_pipe or one
|
||
of the socket functions. */
|
||
static int
|
||
my_close (assuan_context_t ctx, assuan_fd_t fd)
|
||
{
|
||
return _gpgme_io_close (fd);
|
||
}
|
||
|
||
|
||
static ssize_t
|
||
my_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
|
||
{
|
||
return _gpgme_io_read (fd, buffer, size);
|
||
}
|
||
|
||
|
||
static ssize_t
|
||
my_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer, size_t size)
|
||
{
|
||
return _gpgme_io_write (fd, buffer, size);
|
||
}
|
||
|
||
|
||
static int
|
||
my_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
|
||
int flags)
|
||
{
|
||
#ifdef HAVE_W32_SYSTEM
|
||
errno = ENOSYS;
|
||
return -1;
|
||
#else
|
||
return _gpgme_io_recvmsg (fd, msg, flags);
|
||
#endif
|
||
}
|
||
|
||
|
||
|
||
static int
|
||
my_sendmsg (assuan_context_t ctx, assuan_fd_t fd, const assuan_msghdr_t msg,
|
||
int flags)
|
||
{
|
||
#ifdef HAVE_W32_SYSTEM
|
||
errno = ENOSYS;
|
||
return -1;
|
||
#else
|
||
return _gpgme_io_sendmsg (fd, msg, flags);
|
||
#endif
|
||
}
|
||
|
||
|
||
/* If NAME is NULL, don't exec, just fork. FD_CHILD_LIST is modified
|
||
to reflect the value of the FD in the peer process (on
|
||
Windows). */
|
||
static int
|
||
my_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
|
||
const char **argv,
|
||
assuan_fd_t fd_in, assuan_fd_t fd_out,
|
||
assuan_fd_t *fd_child_list,
|
||
void (*atfork) (void *opaque, int reserved),
|
||
void *atforkvalue, unsigned int flags)
|
||
{
|
||
int err;
|
||
struct spawn_fd_item_s *fd_items;
|
||
int i;
|
||
|
||
assert (name);
|
||
|
||
if (! name)
|
||
{
|
||
errno = ENOSYS;
|
||
return -1;
|
||
}
|
||
|
||
i = 0;
|
||
if (fd_child_list)
|
||
{
|
||
while (fd_child_list[i] != ASSUAN_INVALID_FD)
|
||
i++;
|
||
}
|
||
/* fd_in, fd_out, terminator */
|
||
i += 3;
|
||
fd_items = malloc (sizeof (struct spawn_fd_item_s) * i);
|
||
if (! fd_items)
|
||
return -1;
|
||
i = 0;
|
||
if (fd_child_list)
|
||
{
|
||
while (fd_child_list[i] != ASSUAN_INVALID_FD)
|
||
{
|
||
fd_items[i].fd = fd_child_list[i];
|
||
fd_items[i].dup_to = -1;
|
||
i++;
|
||
}
|
||
}
|
||
if (fd_in != ASSUAN_INVALID_FD)
|
||
{
|
||
fd_items[i].fd = fd_in;
|
||
fd_items[i].dup_to = 0;
|
||
i++;
|
||
}
|
||
if (fd_out != ASSUAN_INVALID_FD)
|
||
{
|
||
fd_items[i].fd = fd_out;
|
||
fd_items[i].dup_to = 1;
|
||
i++;
|
||
}
|
||
fd_items[i].fd = -1;
|
||
fd_items[i].dup_to = -1;
|
||
|
||
err = _gpgme_io_spawn (name, argv, IOSPAWN_FLAG_NOCLOSE, fd_items,
|
||
atfork, atforkvalue, r_pid);
|
||
if (! err)
|
||
{
|
||
i = 0;
|
||
|
||
if (fd_child_list)
|
||
{
|
||
while (fd_child_list[i] != ASSUAN_INVALID_FD)
|
||
{
|
||
fd_child_list[i] = fd_items[i].peer_name;
|
||
i++;
|
||
}
|
||
}
|
||
}
|
||
free (fd_items);
|
||
return err;
|
||
}
|
||
|
||
|
||
/* If action is 0, like waitpid. If action is 1, just release the PID? */
|
||
static pid_t
|
||
my_waitpid (assuan_context_t ctx, pid_t pid,
|
||
int nowait, int *status, int options)
|
||
{
|
||
#ifdef HAVE_W32_SYSTEM
|
||
CloseHandle ((HANDLE) pid);
|
||
#else
|
||
/* We can't just release the PID, a waitpid is mandatory. But
|
||
NOWAIT in POSIX systems just means the caller already did the
|
||
waitpid for this child. */
|
||
if (! nowait)
|
||
return _gpgme_ath_waitpid (pid, status, options);
|
||
#endif
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
|
||
static int
|
||
my_socketpair (assuan_context_t ctx, int namespace, int style,
|
||
int protocol, assuan_fd_t filedes[2])
|
||
{
|
||
#ifdef HAVE_W32_SYSTEM
|
||
errno = ENOSYS;
|
||
return -1;
|
||
#else
|
||
/* FIXME: Debug output missing. */
|
||
return __assuan_socketpair (ctx, namespace, style, protocol, filedes);
|
||
#endif
|
||
}
|
||
|
||
|
||
struct assuan_system_hooks _gpgme_assuan_system_hooks =
|
||
{
|
||
ASSUAN_SYSTEM_HOOKS_VERSION,
|
||
my_usleep,
|
||
my_pipe,
|
||
my_close,
|
||
my_read,
|
||
my_write,
|
||
my_recvmsg,
|
||
my_sendmsg,
|
||
my_spawn,
|
||
my_waitpid,
|
||
my_socketpair
|
||
};
|
||
|