|
Packit Service |
0ef63b |
/* assuan-support.c - Assuan wrappers
|
|
Packit Service |
0ef63b |
* Copyright (C) 2009 g10 Code GmbH
|
|
Packit Service |
0ef63b |
*
|
|
Packit Service |
0ef63b |
* This file is part of GPGME.
|
|
Packit Service |
0ef63b |
*
|
|
Packit Service |
0ef63b |
* GPGME is free software; you can redistribute it and/or modify it
|
|
Packit Service |
0ef63b |
* under the terms of the GNU Lesser General Public License as
|
|
Packit Service |
0ef63b |
* published by the Free Software Foundation; either version 2.1 of
|
|
Packit Service |
0ef63b |
* the License, or (at your option) any later version.
|
|
Packit Service |
0ef63b |
*
|
|
Packit Service |
0ef63b |
* GPGME is distributed in the hope that it will be useful, but
|
|
Packit Service |
0ef63b |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
0ef63b |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
0ef63b |
* Lesser General Public License for more details.
|
|
Packit Service |
0ef63b |
*
|
|
Packit Service |
0ef63b |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit Service |
0ef63b |
* License along with this program; if not, see <https://gnu.org/licenses/>.
|
|
Packit Service |
0ef63b |
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
Packit Service |
0ef63b |
*/
|
|
Packit Service |
0ef63b |
|
|
Packit Service |
0ef63b |
|
|
Packit Service |
672cf4 |
#if HAVE_CONFIG_H
|
|
Packit Service |
672cf4 |
#include <config.h>
|
|
Packit Service |
672cf4 |
#endif
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
#include <assert.h>
|
|
Packit Service |
672cf4 |
#include <stdlib.h>
|
|
Packit Service |
672cf4 |
#include <errno.h>
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
#include "assuan.h"
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
#include "gpgme.h"
|
|
Packit Service |
672cf4 |
#include "ath.h"
|
|
Packit Service |
672cf4 |
#include "priv-io.h"
|
|
Packit Service |
672cf4 |
#include "debug.h"
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
struct assuan_malloc_hooks _gpgme_assuan_malloc_hooks =
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
malloc,
|
|
Packit Service |
672cf4 |
realloc,
|
|
Packit Service |
672cf4 |
free
|
|
Packit Service |
672cf4 |
};
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
int
|
|
Packit Service |
672cf4 |
_gpgme_assuan_log_cb (assuan_context_t ctx, void *hook,
|
|
Packit Service |
672cf4 |
unsigned int cat, const char *msg)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
(void)ctx;
|
|
Packit Service |
672cf4 |
(void)hook;
|
|
Packit Service |
672cf4 |
(void)cat;
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
if (msg == NULL)
|
|
Packit Service |
672cf4 |
return 1;
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
0ef63b |
_gpgme_debug (NULL, DEBUG_ASSUAN, -1, NULL, NULL, NULL, "%s", msg);
|
|
Packit Service |
672cf4 |
return 0;
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
static void
|
|
Packit Service |
672cf4 |
my_usleep (assuan_context_t ctx, unsigned int usec)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
/* FIXME: Add to ath. */
|
|
Packit Service |
672cf4 |
__assuan_usleep (ctx, usec);
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
/* Create a pipe with an inheritable end. */
|
|
Packit Service |
672cf4 |
static int
|
|
Packit Service |
672cf4 |
my_pipe (assuan_context_t ctx, assuan_fd_t fds[2], int inherit_idx)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
int res;
|
|
Packit Service |
672cf4 |
int gfds[2];
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
(void)ctx;
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
res = _gpgme_io_pipe (gfds, inherit_idx);
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
/* For now... */
|
|
Packit Service |
672cf4 |
fds[0] = (assuan_fd_t) gfds[0];
|
|
Packit Service |
672cf4 |
fds[1] = (assuan_fd_t) gfds[1];
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
return res;
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
/* Close the given file descriptor, created with _assuan_pipe or one
|
|
Packit Service |
672cf4 |
of the socket functions. */
|
|
Packit Service |
672cf4 |
static int
|
|
Packit Service |
672cf4 |
my_close (assuan_context_t ctx, assuan_fd_t fd)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
(void)ctx;
|
|
Packit Service |
672cf4 |
return _gpgme_io_close ((int) fd);
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
static gpgme_ssize_t
|
|
Packit Service |
672cf4 |
my_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
(void)ctx;
|
|
Packit Service |
672cf4 |
return _gpgme_io_read ((int) fd, buffer, size);
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
static gpgme_ssize_t
|
|
Packit Service |
672cf4 |
my_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer, size_t size)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
(void)ctx;
|
|
Packit Service |
672cf4 |
return _gpgme_io_write ((int) fd, buffer, size);
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
static int
|
|
Packit Service |
672cf4 |
my_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
|
|
Packit Service |
672cf4 |
int flags)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
(void)ctx;
|
|
Packit Service |
672cf4 |
#ifdef HAVE_W32_SYSTEM
|
|
Packit Service |
672cf4 |
(void)fd;
|
|
Packit Service |
672cf4 |
(void)msg;
|
|
Packit Service |
672cf4 |
(void)flags;
|
|
Packit Service |
672cf4 |
gpg_err_set_errno (ENOSYS);
|
|
Packit Service |
672cf4 |
return -1;
|
|
Packit Service |
672cf4 |
#else
|
|
Packit Service |
672cf4 |
return _gpgme_io_recvmsg ((int) fd, msg, flags);
|
|
Packit Service |
672cf4 |
#endif
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
static int
|
|
Packit Service |
672cf4 |
my_sendmsg (assuan_context_t ctx, assuan_fd_t fd, const assuan_msghdr_t msg,
|
|
Packit Service |
672cf4 |
int flags)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
(void)ctx;
|
|
Packit Service |
672cf4 |
#ifdef HAVE_W32_SYSTEM
|
|
Packit Service |
672cf4 |
(void)fd;
|
|
Packit Service |
672cf4 |
(void)msg;
|
|
Packit Service |
672cf4 |
(void)flags;
|
|
Packit Service |
672cf4 |
gpg_err_set_errno (ENOSYS);
|
|
Packit Service |
672cf4 |
return -1;
|
|
Packit Service |
672cf4 |
#else
|
|
Packit Service |
672cf4 |
return _gpgme_io_sendmsg ((int) fd, msg, flags);
|
|
Packit Service |
672cf4 |
#endif
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
/* If NAME is NULL, don't exec, just fork. FD_CHILD_LIST is modified
|
|
Packit Service |
672cf4 |
to reflect the value of the FD in the peer process (on
|
|
Packit Service |
672cf4 |
Windows). */
|
|
Packit Service |
672cf4 |
static int
|
|
Packit Service |
672cf4 |
my_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
|
|
Packit Service |
672cf4 |
const char **argv,
|
|
Packit Service |
672cf4 |
assuan_fd_t fd_in, assuan_fd_t fd_out,
|
|
Packit Service |
672cf4 |
assuan_fd_t *fd_child_list,
|
|
Packit Service |
672cf4 |
void (*atfork) (void *opaque, int reserved),
|
|
Packit Service |
672cf4 |
void *atforkvalue, unsigned int flags)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
0ef63b |
int err = 0;
|
|
Packit Service |
672cf4 |
struct spawn_fd_item_s *fd_items;
|
|
Packit Service |
672cf4 |
int i;
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
(void)ctx;
|
|
Packit Service |
672cf4 |
(void)flags;
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
assert (name);
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
if (! name)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
gpg_err_set_errno (ENOSYS);
|
|
Packit Service |
672cf4 |
return -1;
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
i = 0;
|
|
Packit Service |
672cf4 |
if (fd_child_list)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
while (fd_child_list[i] != ASSUAN_INVALID_FD)
|
|
Packit Service |
672cf4 |
i++;
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
/* fd_in, fd_out, terminator */
|
|
Packit Service |
672cf4 |
i += 3;
|
|
Packit Service |
672cf4 |
fd_items = calloc (i, sizeof (struct spawn_fd_item_s));
|
|
Packit Service |
672cf4 |
if (! fd_items)
|
|
Packit Service |
672cf4 |
return -1;
|
|
Packit Service |
672cf4 |
i = 0;
|
|
Packit Service |
672cf4 |
if (fd_child_list)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
while (fd_child_list[i] != ASSUAN_INVALID_FD)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
fd_items[i].fd = (int) fd_child_list[i];
|
|
Packit Service |
672cf4 |
fd_items[i].dup_to = -1;
|
|
Packit Service |
672cf4 |
i++;
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
if (fd_in != ASSUAN_INVALID_FD)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
fd_items[i].fd = (int) fd_in;
|
|
Packit Service |
672cf4 |
fd_items[i].dup_to = 0;
|
|
Packit Service |
672cf4 |
i++;
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
if (fd_out != ASSUAN_INVALID_FD)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
fd_items[i].fd = (int) fd_out;
|
|
Packit Service |
672cf4 |
fd_items[i].dup_to = 1;
|
|
Packit Service |
672cf4 |
i++;
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
fd_items[i].fd = -1;
|
|
Packit Service |
672cf4 |
fd_items[i].dup_to = -1;
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
0ef63b |
#ifdef HAVE_W32_SYSTEM
|
|
Packit Service |
0ef63b |
/* Fix up a potential logger fd so that on windows the fd
|
|
Packit Service |
0ef63b |
* translation can work through gpgme-w32spawn.
|
|
Packit Service |
0ef63b |
*
|
|
Packit Service |
0ef63b |
* We do this here as a hack because we would
|
|
Packit Service |
0ef63b |
* otherwise have to change assuan_api and the current
|
|
Packit Service |
0ef63b |
* plan in 2019 is to change away from this to gpgrt
|
|
Packit Service |
0ef63b |
* based IPC. */
|
|
Packit Service |
0ef63b |
if (argv)
|
|
Packit Service |
0ef63b |
{
|
|
Packit Service |
0ef63b |
int loc = 0;
|
|
Packit Service |
0ef63b |
while (argv[loc])
|
|
Packit Service |
0ef63b |
{
|
|
Packit Service |
0ef63b |
if (!strcmp ("--logger-fd", argv[loc]))
|
|
Packit Service |
0ef63b |
{
|
|
Packit Service |
0ef63b |
long logger_fd = -1;
|
|
Packit Service |
0ef63b |
char *tail;
|
|
Packit Service |
0ef63b |
int k = 0;
|
|
Packit Service |
0ef63b |
loc++;
|
|
Packit Service |
0ef63b |
if (!argv[loc])
|
|
Packit Service |
0ef63b |
{
|
|
Packit Service |
0ef63b |
err = GPG_ERR_INV_ARG;
|
|
Packit Service |
0ef63b |
break;
|
|
Packit Service |
0ef63b |
}
|
|
Packit Service |
0ef63b |
logger_fd = strtol (argv[loc], &tail, 10);
|
|
Packit Service |
0ef63b |
if (tail == argv[loc] || logger_fd < 0)
|
|
Packit Service |
0ef63b |
{
|
|
Packit Service |
0ef63b |
err = GPG_ERR_INV_ARG;
|
|
Packit Service |
0ef63b |
break;
|
|
Packit Service |
0ef63b |
}
|
|
Packit Service |
0ef63b |
while (fd_items[k++].fd != -1)
|
|
Packit Service |
0ef63b |
{
|
|
Packit Service |
0ef63b |
if (fd_items[k].fd == logger_fd)
|
|
Packit Service |
0ef63b |
{
|
|
Packit Service |
0ef63b |
fd_items[k].arg_loc = loc;
|
|
Packit Service |
0ef63b |
break;
|
|
Packit Service |
0ef63b |
}
|
|
Packit Service |
0ef63b |
}
|
|
Packit Service |
0ef63b |
break;
|
|
Packit Service |
0ef63b |
}
|
|
Packit Service |
0ef63b |
loc++;
|
|
Packit Service |
0ef63b |
}
|
|
Packit Service |
0ef63b |
}
|
|
Packit Service |
0ef63b |
#endif
|
|
Packit Service |
0ef63b |
|
|
Packit Service |
0ef63b |
if (!err)
|
|
Packit Service |
0ef63b |
{
|
|
Packit Service |
0ef63b |
err = _gpgme_io_spawn (name, (char*const*)argv,
|
|
Packit Service |
0ef63b |
(IOSPAWN_FLAG_NOCLOSE | IOSPAWN_FLAG_DETACHED),
|
|
Packit Service |
0ef63b |
fd_items, atfork, atforkvalue, r_pid);
|
|
Packit Service |
0ef63b |
}
|
|
Packit Service |
0ef63b |
if (!err)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
i = 0;
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
if (fd_child_list)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
while (fd_child_list[i] != ASSUAN_INVALID_FD)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
fd_child_list[i] = (assuan_fd_t) fd_items[i].peer_name;
|
|
Packit Service |
672cf4 |
i++;
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
free (fd_items);
|
|
Packit Service |
672cf4 |
return err;
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
/* If action is 0, like waitpid. If action is 1, just release the PID? */
|
|
Packit Service |
672cf4 |
static pid_t
|
|
Packit Service |
672cf4 |
my_waitpid (assuan_context_t ctx, pid_t pid,
|
|
Packit Service |
672cf4 |
int nowait, int *status, int options)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
(void)ctx;
|
|
Packit Service |
672cf4 |
#ifdef HAVE_W32_SYSTEM
|
|
Packit Service |
672cf4 |
(void)nowait;
|
|
Packit Service |
672cf4 |
(void)status;
|
|
Packit Service |
672cf4 |
(void)options;
|
|
Packit Service |
0ef63b |
(void)pid; /* Just a number without a kernel object. */
|
|
Packit Service |
672cf4 |
#else
|
|
Packit Service |
672cf4 |
/* We can't just release the PID, a waitpid is mandatory. But
|
|
Packit Service |
672cf4 |
NOWAIT in POSIX systems just means the caller already did the
|
|
Packit Service |
672cf4 |
waitpid for this child. */
|
|
Packit Service |
672cf4 |
if (! nowait)
|
|
Packit Service |
672cf4 |
return _gpgme_ath_waitpid (pid, status, options);
|
|
Packit Service |
672cf4 |
#endif
|
|
Packit Service |
672cf4 |
return 0;
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
static int
|
|
Packit Service |
672cf4 |
my_socketpair (assuan_context_t ctx, int namespace, int style,
|
|
Packit Service |
672cf4 |
int protocol, assuan_fd_t filedes[2])
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
#ifdef HAVE_W32_SYSTEM
|
|
Packit Service |
672cf4 |
(void)ctx;
|
|
Packit Service |
672cf4 |
(void)namespace;
|
|
Packit Service |
672cf4 |
(void)style;
|
|
Packit Service |
672cf4 |
(void)protocol;
|
|
Packit Service |
672cf4 |
(void)filedes;
|
|
Packit Service |
672cf4 |
gpg_err_set_errno (ENOSYS);
|
|
Packit Service |
672cf4 |
return -1;
|
|
Packit Service |
672cf4 |
#else
|
|
Packit Service |
672cf4 |
/* FIXME: Debug output missing. */
|
|
Packit Service |
672cf4 |
return __assuan_socketpair (ctx, namespace, style, protocol, filedes);
|
|
Packit Service |
672cf4 |
#endif
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
static int
|
|
Packit Service |
672cf4 |
my_socket (assuan_context_t ctx, int namespace, int style, int protocol)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
(void)ctx;
|
|
Packit Service |
672cf4 |
return _gpgme_io_socket (namespace, style, protocol);
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
static int
|
|
Packit Service |
672cf4 |
my_connect (assuan_context_t ctx, int sock, struct sockaddr *addr,
|
|
Packit Service |
672cf4 |
socklen_t length)
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
(void)ctx;
|
|
Packit Service |
672cf4 |
return _gpgme_io_connect (sock, addr, length);
|
|
Packit Service |
672cf4 |
}
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
|
|
Packit Service |
672cf4 |
/* Note for Windows: Ignore the incompatible pointer type warning for
|
|
Packit Service |
672cf4 |
my_read and my_write. Mingw has been changed to use int for
|
|
Packit Service |
672cf4 |
ssize_t on 32 bit systems while we use long. For 64 bit we use
|
|
Packit Service |
672cf4 |
int64_t while mingw uses __int64_t. It doe not matter at all
|
|
Packit Service |
672cf4 |
because under Windows long and int are both 32 bit even on 64
|
|
Packit Service |
672cf4 |
bit. */
|
|
Packit Service |
672cf4 |
struct assuan_system_hooks _gpgme_assuan_system_hooks =
|
|
Packit Service |
672cf4 |
{
|
|
Packit Service |
672cf4 |
ASSUAN_SYSTEM_HOOKS_VERSION,
|
|
Packit Service |
672cf4 |
my_usleep,
|
|
Packit Service |
672cf4 |
my_pipe,
|
|
Packit Service |
672cf4 |
my_close,
|
|
Packit Service |
672cf4 |
my_read,
|
|
Packit Service |
672cf4 |
my_write,
|
|
Packit Service |
672cf4 |
my_recvmsg,
|
|
Packit Service |
672cf4 |
my_sendmsg,
|
|
Packit Service |
672cf4 |
my_spawn,
|
|
Packit Service |
672cf4 |
my_waitpid,
|
|
Packit Service |
672cf4 |
my_socketpair,
|
|
Packit Service |
672cf4 |
my_socket,
|
|
Packit Service |
672cf4 |
my_connect
|
|
Packit Service |
672cf4 |
};
|