2009-10-20 Marcus Brinkmann <marcus@g10code.de>

* configure.ac: Replace internal libassuan by external libassuan.
	* m4/libassuan.m4: New file.
	* Makefile.am (assuan): Remove variable.
	(SUBDIRS): Remove ${assuan}.
	* assuan/: Removed.

src/
2009-10-20  Marcus Brinkmann  <marcus@g10code.de>

	* Makefile.am (assuan_cppflags, assuan_libobjs): Removed.
	(gpgsm_components): Move engine-assuan.c to ...
	(assuan_components): ... this new variable.
	(main_sources): Add this new variable.
	(AM_CPPFLAGS): Remove $(assuan_cppflags).
	(AM_CFLAGS): Add @LIBASSUAN_CFLAGS@.
	(libgpgme_la_DEPENDENCIES, libgpgme_pth_la_DEPENDENCIES)
	(libgpgme_glib_la_DEPENDENCIES, libgpgme_qt_la_DEPENDENCIES)
	(libgpgme_pthread_la_DEPENDENCIES): Remove $(assuan_libobjs).
	(libgpgme_la_LIBADD, libgpgme_pth_la_LIBADD)
	(libgpgme_glib_la_LIBADD, libgpgme_qt_la_LIBADD))
	(libgpgme_pthread_la_LIBADD): Replace $(assuan_libobjs) by
	@LIBASSUAN_LIBS@.
	* priv-io.h [!HAVE_W32_SYSTEM]: Declare _gpgme_io_recvmsg,
	_gpgme_io_sendmsg, _gpgme_io_waitpid.
	* engine-backend.h: Define with [ENABLE_ASSUAN] instead
	of [ENABLE_GPGSM].
	* posix-io.c (_gpgme_io_waitpid): Make non-static.
	* util.h (ENABLE_ASSUAN): Declar _gpgme_assuan_system_hooks,
	_gpgme_assuan_malloc_hooks, _gpgme_assuan_log_cb.
	* engine-gpgsm.c: Don't map assuan error codes.  Use
	assuan_release instead of assuan_disconnect.
	(map_assuan_error): Remove function.
	(gpgsm_new): Use new assuan context interface.
	* engine-assuan.c: Use assuan_release instead of
	assuan_disconnect.
	(llass_new): Use new assuan context interface.
This commit is contained in:
Marcus Brinkmann 2009-10-20 15:39:15 +00:00
parent 06e22ca339
commit e782b1ab06
33 changed files with 227 additions and 8443 deletions

View File

@ -1,3 +1,11 @@
2009-10-20 Marcus Brinkmann <marcus@g10code.de>
* configure.ac: Replace internal libassuan by external libassuan.
* m4/libassuan.m4: New file.
* Makefile.am (assuan): Remove variable.
(SUBDIRS): Remove ${assuan}.
* assuan/: Removed.
2009-06-22 Marcus Brinkmann <marcus@g10code.de>
* configure.ac: Add AC_TYPE_UINTPTR_T.

View File

@ -26,11 +26,6 @@ DISTCHECK_CONFIGURE_FLAGS = --with-gpg="@GPG@"
EXTRA_DIST = gpgme.spec.in autogen.sh
if BUILD_ASSUAN
assuan = assuan
else
assuan =
endif
if BUILD_COMPLUS
complus = complus
@ -44,7 +39,7 @@ else
tests =
endif
SUBDIRS = ${assuan} src ${tests} doc ${complus} lang
SUBDIRS = src ${tests} doc ${complus} lang
# Fix the version of the spec file and create a file named VERSION
# to be used for patch's Prereq: feature.

File diff suppressed because it is too large Load Diff

View File

@ -1,53 +0,0 @@
# Assuan Makefile
# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
#
# This file is part of Assuan.
#
# Assuan is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of
# the License, or (at your option) any later version.
#
# Assuan is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
## Process this file with automake to produce Makefile.in
EXTRA_DIST = mkerrors
INCLUDES = -I.. -I$(top_srcdir)/src
BUILT_SOURCES = assuan-errors.c
MOSTLYCLEANFILES = assuan-errors.c
noinst_LTLIBRARIES = libassuan.la
AM_CPPFLAGS = -D_ASSUAN_IN_GPGME_BUILD_ASSUAN
#libassuan_la_LDFLAGS =
libassuan_la_SOURCES = \
assuan.h \
assuan-defs.h \
assuan-util.c \
assuan-errors.c \
assuan-buffer.c \
assuan-handler.c \
assuan-inquire.c \
assuan-listen.c \
assuan-connect.c \
assuan-client.c \
assuan-pipe-server.c \
assuan-socket-server.c \
assuan-pipe-connect.c \
assuan-socket-connect.c \
assuan-uds.c \
assuan-io.c \
assuan-logging.c \
assuan-socket.c
assuan-errors.c : assuan.h mkerrors
$(srcdir)/mkerrors < $(srcdir)/assuan.h > assuan-errors.c

View File

@ -1,45 +0,0 @@
This is a modified copy of the libassuan library. Don't modify it,
but instead modify the original Assuan library and merge the changes
back into this copy.
The changes to the original libassuan, that have to preserved when
updating this directory, are:
* Makefile.am
** Build the library with libtool as a convenience library, which can
be linked into the shared library GPGME.
** Do not install the library or the header file.
** Define -D_ASSUAN_IN_GPGME_BUILD_ASSUAN to wrap some POSIX functions
with ATH replacements.
* assuan.h
** Preserve the block between "Begin/End GPGME specific modifications".
In particular make sure that
#define _ASSUAN_EXT_SYM_PREFIX _gpgme_
#define _ASSUAN_NO_PTH
#define _ASSUAN_NO_FIXED_SIGNALS
#define _ASSUAN_USE_DOUBLE_FORK
are defined. This puts all exported Assuan functions in the _gpgme
namespace. It also wraps all system functions that are wrapped by
GNU Pth to _gpgme wrappers.
* assuan-io-pth.c
We don't need this file as GPGME doesn't use sendmsg and recvmsg.
If it would, we would need to pick up the W32 implementation.
* assuan-io.c
** _assuan_simple_read() and _assuan_simple_write() must always use
read()/write() (which actually translates to _gpgme_io_read() and
_gpgme_io_write()). _assuan_close must always() use close() (which
translates to _gpgme_io_close()).
Copyright 2004, 2007 g10 Code GmbH
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
modifications, as long as this notice is preserved.
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

View File

@ -1,565 +0,0 @@
/* assuan-buffer.c - read and send data
* Copyright (C) 2001, 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <assert.h>
#ifdef HAVE_W32_SYSTEM
#include <process.h>
#endif
#include "assuan-defs.h"
/* Extended version of write(2) to guarantee that all bytes are
written. Returns 0 on success or -1 and ERRNO on failure. */
static int
writen (assuan_context_t ctx, const char *buffer, size_t length)
{
while (length)
{
ssize_t nwritten = ctx->io->writefnc (ctx, buffer, length);
if (nwritten < 0)
{
if (errno == EINTR)
continue;
return -1; /* write error */
}
length -= nwritten;
buffer += nwritten;
}
return 0; /* okay */
}
/* Read an entire line. Returns 0 on success or -1 and ERRNO on
failure. EOF is indictated by setting the integer at address
R_EOF. Note: BUF, R_NREAD and R_EOF contain a valid result even if
an error is returned. */
static int
readline (assuan_context_t ctx, char *buf, size_t buflen,
int *r_nread, int *r_eof)
{
size_t nleft = buflen;
char *p;
*r_eof = 0;
*r_nread = 0;
while (nleft > 0)
{
ssize_t n = ctx->io->readfnc (ctx, buf, nleft);
if (n < 0)
{
if (errno == EINTR)
continue;
return -1; /* read error */
}
else if (!n)
{
*r_eof = 1;
break; /* allow incomplete lines */
}
p = buf;
nleft -= n;
buf += n;
*r_nread += n;
p = memrchr (p, '\n', n);
if (p)
break; /* at least one full line available - that's enough for now */
}
return 0;
}
/* Function returns an Assuan error. */
assuan_error_t
_assuan_read_line (assuan_context_t ctx)
{
char *line = ctx->inbound.line;
int nread, atticlen;
int rc;
char *endp = 0;
if (ctx->inbound.eof)
return _assuan_error (-1);
atticlen = ctx->inbound.attic.linelen;
if (atticlen)
{
memcpy (line, ctx->inbound.attic.line, atticlen);
ctx->inbound.attic.linelen = 0;
endp = memchr (line, '\n', atticlen);
if (endp)
/* Found another line in the attic. */
{
rc = 0;
nread = atticlen;
atticlen = 0;
}
else
/* There is pending data but not a full line. */
{
assert (atticlen < LINELENGTH);
rc = readline (ctx, line + atticlen,
LINELENGTH - atticlen, &nread, &ctx->inbound.eof);
}
}
else
/* No pending data. */
rc = readline (ctx, line, LINELENGTH,
&nread, &ctx->inbound.eof);
if (rc)
{
int saved_errno = errno;
if (ctx->log_fp)
fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Error: %s]\n",
assuan_get_assuan_log_prefix (),
(unsigned int)getpid (), (int)ctx->inbound.fd,
strerror (errno));
if (saved_errno == EAGAIN)
{
/* We have to save a partial line. */
memcpy (ctx->inbound.attic.line, line, atticlen + nread);
ctx->inbound.attic.pending = 0;
ctx->inbound.attic.linelen = atticlen + nread;
}
errno = saved_errno;
return _assuan_error (ASSUAN_Read_Error);
}
if (!nread)
{
assert (ctx->inbound.eof);
if (ctx->log_fp)
fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [EOF]\n",
assuan_get_assuan_log_prefix (),
(unsigned int)getpid (), (int)ctx->inbound.fd);
return _assuan_error (-1);
}
ctx->inbound.attic.pending = 0;
nread += atticlen;
if (! endp)
endp = memchr (line, '\n', nread);
if (endp)
{
unsigned monitor_result;
int n = endp - line + 1;
if (n < nread)
/* LINE contains more than one line. We copy it to the attic
now as handlers are allowed to modify the passed
buffer. */
{
int len = nread - n;
memcpy (ctx->inbound.attic.line, endp + 1, len);
ctx->inbound.attic.pending = memrchr (endp + 1, '\n', len) ? 1 : 0;
ctx->inbound.attic.linelen = len;
}
if (endp != line && endp[-1] == '\r')
endp --;
*endp = 0;
ctx->inbound.linelen = endp - line;
monitor_result = (ctx->io_monitor
? ctx->io_monitor (ctx, 0,
ctx->inbound.line,
ctx->inbound.linelen)
: 0);
if ( (monitor_result & 2) )
ctx->inbound.linelen = 0;
if (ctx->log_fp && !(monitor_result & 1))
{
fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- ",
assuan_get_assuan_log_prefix (),
(unsigned int)getpid (), (int)ctx->inbound.fd);
if (ctx->confidential)
fputs ("[Confidential data not shown]", ctx->log_fp);
else
_assuan_log_print_buffer (ctx->log_fp,
ctx->inbound.line,
ctx->inbound.linelen);
putc ('\n', ctx->log_fp);
}
return 0;
}
else
{
if (ctx->log_fp)
fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Invalid line]\n",
assuan_get_assuan_log_prefix (),
(unsigned int)getpid (), (int)ctx->inbound.fd);
*line = 0;
ctx->inbound.linelen = 0;
return _assuan_error (ctx->inbound.eof
? ASSUAN_Line_Not_Terminated
: ASSUAN_Line_Too_Long);
}
}
/* Read the next line from the client or server and return a pointer
in *LINE to a buffer holding the line. LINELEN is the length of
*LINE. The buffer is valid until the next read operation on it.
The caller may modify the buffer. The buffer is invalid (i.e. must
not be used) if an error is returned.
Returns 0 on success or an assuan error code.
See also: assuan_pending_line().
*/
assuan_error_t
assuan_read_line (assuan_context_t ctx, char **line, size_t *linelen)
{
assuan_error_t err;
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
err = _assuan_read_line (ctx);
*line = ctx->inbound.line;
*linelen = ctx->inbound.linelen;
return err;
}
/* Return true if a full line is buffered (i.e. an entire line may be
read without any I/O). */
int
assuan_pending_line (assuan_context_t ctx)
{
return ctx && ctx->inbound.attic.pending;
}
assuan_error_t
_assuan_write_line (assuan_context_t ctx, const char *prefix,
const char *line, size_t len)
{
assuan_error_t rc = 0;
size_t prefixlen = prefix? strlen (prefix):0;
unsigned int monitor_result;
/* Make sure that the line is short enough. */
if (len + prefixlen + 2 > ASSUAN_LINELENGTH)
{
if (ctx->log_fp)
fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> "
"[supplied line too long -truncated]\n",
assuan_get_assuan_log_prefix (),
(unsigned int)getpid (), (int)ctx->inbound.fd);
if (prefixlen > 5)
prefixlen = 5;
if (len > ASSUAN_LINELENGTH - prefixlen - 2)
len = ASSUAN_LINELENGTH - prefixlen - 2 - 1;
}
monitor_result = (ctx->io_monitor
? ctx->io_monitor (ctx, 1, line, len)
: 0);
/* Fixme: we should do some kind of line buffering. */
if (ctx->log_fp && !(monitor_result & 1))
{
fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
assuan_get_assuan_log_prefix (),
(unsigned int)getpid (), (int)ctx->inbound.fd);
if (ctx->confidential)
fputs ("[Confidential data not shown]", ctx->log_fp);
else
{
if (prefixlen)
_assuan_log_print_buffer (ctx->log_fp, prefix, prefixlen);
_assuan_log_print_buffer (ctx->log_fp, line, len);
}
putc ('\n', ctx->log_fp);
}
if (prefixlen && !(monitor_result & 2))
{
rc = writen (ctx, prefix, prefixlen);
if (rc)
rc = _assuan_error (ASSUAN_Write_Error);
}
if (!rc && !(monitor_result & 2))
{
rc = writen (ctx, line, len);
if (rc)
rc = _assuan_error (ASSUAN_Write_Error);
if (!rc)
{
rc = writen (ctx, "\n", 1);
if (rc)
rc = _assuan_error (ASSUAN_Write_Error);
}
}
return rc;
}
assuan_error_t
assuan_write_line (assuan_context_t ctx, const char *line)
{
size_t len;
const char *s;
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
/* Make sure that we never take a LF from the user - this might
violate the protocol. */
s = strchr (line, '\n');
len = s? (s-line) : strlen (line);
if (ctx->log_fp && s)
fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> "
"[supplied line contained a LF - truncated]\n",
assuan_get_assuan_log_prefix (),
(unsigned int)getpid (), (int)ctx->inbound.fd);
return _assuan_write_line (ctx, NULL, line, len);
}
/* Write out the data in buffer as datalines with line wrapping and
percent escaping. This function is used for GNU's custom streams. */
int
_assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
{
assuan_context_t ctx = cookie;
size_t size = orig_size;
char *line;
size_t linelen;
if (ctx->outbound.data.error)
return 0;
line = ctx->outbound.data.line;
linelen = ctx->outbound.data.linelen;
line += linelen;
while (size)
{
unsigned int monitor_result;
/* Insert data line header. */
if (!linelen)
{
*line++ = 'D';
*line++ = ' ';
linelen += 2;
}
/* Copy data, keep space for the CRLF and to escape one character. */
while (size && linelen < LINELENGTH-2-2)
{
if (*buffer == '%' || *buffer == '\r' || *buffer == '\n')
{
sprintf (line, "%%%02X", *(unsigned char*)buffer);
line += 3;
linelen += 3;
buffer++;
}
else
{
*line++ = *buffer++;
linelen++;
}
size--;
}
monitor_result = (ctx->io_monitor
? ctx->io_monitor (ctx, 1,
ctx->outbound.data.line, linelen)
: 0);
if (linelen >= LINELENGTH-2-2)
{
if (ctx->log_fp && !(monitor_result & 1))
{
fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
assuan_get_assuan_log_prefix (),
(unsigned int)getpid (), (int)ctx->inbound.fd);
if (ctx->confidential)
fputs ("[Confidential data not shown]", ctx->log_fp);
else
_assuan_log_print_buffer (ctx->log_fp,
ctx->outbound.data.line,
linelen);
putc ('\n', ctx->log_fp);
}
*line++ = '\n';
linelen++;
if ( !(monitor_result & 2)
&& writen (ctx, ctx->outbound.data.line, linelen))
{
ctx->outbound.data.error = _assuan_error (ASSUAN_Write_Error);
return 0;
}
line = ctx->outbound.data.line;
linelen = 0;
}
}
ctx->outbound.data.linelen = linelen;
return (int)orig_size;
}
/* Write out any buffered data
This function is used for GNU's custom streams */
int
_assuan_cookie_write_flush (void *cookie)
{
assuan_context_t ctx = cookie;
char *line;
size_t linelen;
unsigned int monitor_result;
if (ctx->outbound.data.error)
return 0;
line = ctx->outbound.data.line;
linelen = ctx->outbound.data.linelen;
line += linelen;
monitor_result = (ctx->io_monitor
? ctx->io_monitor (ctx, 1,
ctx->outbound.data.line, linelen)
: 0);
if (linelen)
{
if (ctx->log_fp && !(monitor_result & 1))
{
fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
assuan_get_assuan_log_prefix (),
(unsigned int)getpid (), (int)ctx->inbound.fd);
if (ctx->confidential)
fputs ("[Confidential data not shown]", ctx->log_fp);
else
_assuan_log_print_buffer (ctx->log_fp,
ctx->outbound.data.line, linelen);
putc ('\n', ctx->log_fp);
}
*line++ = '\n';
linelen++;
if ( !(monitor_result & 2)
&& writen (ctx, ctx->outbound.data.line, linelen))
{
ctx->outbound.data.error = _assuan_error (ASSUAN_Write_Error);
return 0;
}
ctx->outbound.data.linelen = 0;
}
return 0;
}
/**
* assuan_send_data:
* @ctx: An assuan context
* @buffer: Data to send or NULL to flush
* @length: length of the data to send/
*
* This function may be used by the server or the client to send data
* lines. The data will be escaped as required by the Assuan protocol
* and may get buffered until a line is full. To force sending the
* data out @buffer may be passed as NULL (in which case @length must
* also be 0); however when used by a client this flush operation does
* also send the terminating "END" command to terminate the reponse on
* a INQUIRE response. However, when assuan_transact() is used, this
* function takes care of sending END itself.
*
* If BUFFER is NULL and LENGTH is 1 and we are a client, a "CAN" is
* send instead of an "END".
*
* Return value: 0 on success or an error code
**/
assuan_error_t
assuan_send_data (assuan_context_t ctx, const void *buffer, size_t length)
{
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
if (!buffer && length > 1)
return _assuan_error (ASSUAN_Invalid_Value);
if (!buffer)
{ /* flush what we have */
_assuan_cookie_write_flush (ctx);
if (ctx->outbound.data.error)
return ctx->outbound.data.error;
if (!ctx->is_server)
return assuan_write_line (ctx, length == 1? "CAN":"END");
}
else
{
_assuan_cookie_write_data (ctx, buffer, length);
if (ctx->outbound.data.error)
return ctx->outbound.data.error;
}
return 0;
}
assuan_error_t
assuan_sendfd (assuan_context_t ctx, assuan_fd_t fd)
{
/* It is explicitly allowed to use (NULL, -1) as a runtime test to
check whether descriptor passing is available. */
if (!ctx && fd == ASSUAN_INVALID_FD)
#ifdef USE_DESCRIPTOR_PASSING
return 0;
#else
return _assuan_error (ASSUAN_Not_Implemented);
#endif
if (! ctx->io->sendfd)
return set_error (ctx, Not_Implemented,
"server does not support sending and receiving "
"of file descriptors");
return ctx->io->sendfd (ctx, fd);
}
assuan_error_t
assuan_receivefd (assuan_context_t ctx, assuan_fd_t *fd)
{
if (! ctx->io->receivefd)
return set_error (ctx, Not_Implemented,
"server does not support sending and receiving "
"of file descriptors");
return ctx->io->receivefd (ctx, fd);
}

View File

@ -1,232 +0,0 @@
/* assuan-client.c - client functions
* Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <assert.h>
#include "assuan-defs.h"
#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
*(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
assuan_error_t
_assuan_read_from_server (assuan_context_t ctx, int *okay, int *off)
{
char *line;
int linelen;
assuan_error_t rc;
*okay = 0;
*off = 0;
do
{
rc = _assuan_read_line (ctx);
if (rc)
return rc;
line = ctx->inbound.line;
linelen = ctx->inbound.linelen;
}
while (*line == '#' || !linelen);
if (linelen >= 1
&& line[0] == 'D' && line[1] == ' ')
{
*okay = 2; /* data line */
*off = 2;
}
else if (linelen >= 1
&& line[0] == 'S'
&& (line[1] == '\0' || line[1] == ' '))
{
*okay = 4;
*off = 1;
while (line[*off] == ' ')
++*off;
}
else if (linelen >= 2
&& line[0] == 'O' && line[1] == 'K'
&& (line[2] == '\0' || line[2] == ' '))
{
*okay = 1;
*off = 2;
while (line[*off] == ' ')
++*off;
}
else if (linelen >= 3
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
&& (line[3] == '\0' || line[3] == ' '))
{
*okay = 0;
*off = 3;
while (line[*off] == ' ')
++*off;
}
else if (linelen >= 7
&& line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
&& line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
&& line[6] == 'E'
&& (line[7] == '\0' || line[7] == ' '))
{
*okay = 3;
*off = 7;
while (line[*off] == ' ')
++*off;
}
else if (linelen >= 3
&& line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
&& (line[3] == '\0' || line[3] == ' '))
{
*okay = 5; /* end line */
*off = 3;
}
else
rc = _assuan_error (ASSUAN_Invalid_Response);
return rc;
}
/**
* assuan_transact:
* @ctx: The Assuan context
* @command: Command line to be send to the server
* @data_cb: Callback function for data lines
* @data_cb_arg: first argument passed to @data_cb
* @inquire_cb: Callback function for a inquire response
* @inquire_cb_arg: first argument passed to @inquire_cb
* @status_cb: Callback function for a status response
* @status_cb_arg: first argument passed to @status_cb
*
* FIXME: Write documentation
*
* Return value: 0 on success or error code. The error code may be
* the one one returned by the server in error lines or from the
* callback functions. Take care: When a callback returns an error
* this function returns immediately with an error and thus the caller
* will altter return an Assuan error (write erro in most cases).
**/
assuan_error_t
assuan_transact (assuan_context_t ctx,
const char *command,
int (*data_cb)(void *, const void *, size_t),
void *data_cb_arg,
int (*inquire_cb)(void*, const char *),
void *inquire_cb_arg,
int (*status_cb)(void*, const char *),
void *status_cb_arg)
{
assuan_error_t rc;
int okay, off;
char *line;
int linelen;
rc = assuan_write_line (ctx, command);
if (rc)
return rc;
if (*command == '#' || !*command)
return 0; /* Don't expect a response for a comment line. */
again:
rc = _assuan_read_from_server (ctx, &okay, &off);
if (rc)
return rc; /* error reading from server */
line = ctx->inbound.line + off;
linelen = ctx->inbound.linelen - off;
if (!okay)
{
rc = atoi (line);
if (rc > 0 && rc < 100)
rc = _assuan_error (ASSUAN_Server_Fault);
else if (rc > 0 && rc <= 405)
rc = _assuan_error (rc);
}
else if (okay == 2)
{
if (!data_cb)
rc = _assuan_error (ASSUAN_No_Data_Callback);
else
{
char *s, *d;
for (s=d=line; linelen; linelen--)
{
if (*s == '%' && linelen > 2)
{ /* handle escaping */
s++;
*d++ = xtoi_2 (s);
s += 2;
linelen -= 2;
}
else
*d++ = *s++;
}
*d = 0; /* add a hidden string terminator */
rc = data_cb (data_cb_arg, line, d - line);
if (!rc)
goto again;
}
}
else if (okay == 3)
{
if (!inquire_cb)
{
assuan_write_line (ctx, "END"); /* get out of inquire mode */
_assuan_read_from_server (ctx, &okay, &off); /* dummy read */
rc = _assuan_error (ASSUAN_No_Inquire_Callback);
}
else
{
rc = inquire_cb (inquire_cb_arg, line);
if (!rc)
rc = assuan_send_data (ctx, NULL, 0); /* flush and send END */
if (!rc)
goto again;
}
}
else if (okay == 4)
{
if (status_cb)
rc = status_cb (status_cb_arg, line);
if (!rc)
goto again;
}
else if (okay == 5)
{
if (!data_cb)
rc = _assuan_error (ASSUAN_No_Data_Callback);
else
{
rc = data_cb (data_cb_arg, NULL, 0);
if (!rc)
goto again;
}
}
return rc;
}

View File

@ -1,83 +0,0 @@
/* assuan-connect.c - Establish a connection (client)
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#ifndef HAVE_W32_SYSTEM
#include <sys/wait.h>
#endif
#include "assuan-defs.h"
/* Disconnect and release the context CTX. */
void
assuan_disconnect (assuan_context_t ctx)
{
if (ctx)
{
assuan_write_line (ctx, "BYE");
ctx->finish_handler (ctx);
ctx->deinit_handler (ctx);
ctx->deinit_handler = NULL;
_assuan_release_context (ctx);
}
}
/* Return the PID of the peer or -1 if not known. This function works
in some situations where assuan_get_ucred fails. */
pid_t
assuan_get_pid (assuan_context_t ctx)
{
return (ctx && ctx->pid)? ctx->pid : -1;
}
#ifndef HAVE_W32_SYSTEM
/* Return user credentials. PID, UID and GID may be given as NULL if
you are not interested in a value. For getting the pid of the
peer the assuan_get_pid is usually better suited. */
assuan_error_t
assuan_get_peercred (assuan_context_t ctx, pid_t *pid, uid_t *uid, gid_t *gid)
{
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
if (!ctx->peercred.valid)
return _assuan_error (ASSUAN_General_Error);
#ifdef HAVE_SO_PEERCRED
if (pid)
*pid = ctx->peercred.pid;
if (uid)
*uid = ctx->peercred.uid;
if (gid)
*gid = ctx->peercred.gid;
#endif
return 0;
}
#endif /* HAVE_W32_SYSTEM */

View File

@ -1,361 +0,0 @@
/* assuan-defs.c - Internal definitions to Assuan
* Copyright (C) 2001, 2002, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef ASSUAN_DEFS_H
#define ASSUAN_DEFS_H
#include <sys/types.h>
#ifndef HAVE_W32_SYSTEM
#include <sys/socket.h>
#include <sys/un.h>
#else
#include <windows.h>
#endif
#include <unistd.h>
#include "assuan.h"
#ifndef HAVE_W32_SYSTEM
#define DIRSEP_C '/'
#else
#define DIRSEP_C '\\'
#endif
#ifdef HAVE_W32_SYSTEM
/* Not needed anymore because the current mingw32 defines this in
sys/types.h */
/* typedef int ssize_t; */
/* Missing W32 functions */
int putc_unlocked (int c, FILE *stream);
void * memrchr (const void *block, int c, size_t size);
char * stpcpy (char *dest, const char *src);
#endif
#define LINELENGTH ASSUAN_LINELENGTH
struct cmdtbl_s
{
const char *name;
int (*handler)(assuan_context_t, char *line);
};
/* A structure to dispatch I/O functions. All these functions need to
return 0 on success and set ERRNO on failure. */
struct assuan_io
{
/* Routine to read from input_fd. */
ssize_t (*readfnc) (assuan_context_t, void *, size_t);
/* Routine to write to output_fd. */
ssize_t (*writefnc) (assuan_context_t, const void *, size_t);
/* Send a file descriptor. */
assuan_error_t (*sendfd) (assuan_context_t, assuan_fd_t);
/* Receive a file descriptor. */
assuan_error_t (*receivefd) (assuan_context_t, assuan_fd_t *);
};
/* The global variable with the optional hook fucntions. */
extern struct assuan_io_hooks _assuan_io_hooks;
/* The context we use with most functions. */
struct assuan_context_s
{
assuan_error_t err_no;
const char *err_str;
int os_errno; /* Last system error number used with certain
error codes. */
/* Context specific flags (cf. assuan_flag_t). */
struct
{
unsigned int no_waitpid:1; /* See ASSUAN_NO_WAITPID. */
} flags;
int confidential;
int is_server; /* Set if this is context belongs to a server */
int in_inquire;
int in_process_next;
int in_command;
/* The following members are used by assuan_inquire_ext. */
int (*inquire_cb) (void *cb_data, int rc, unsigned char *buf, size_t len);
void *inquire_cb_data;
void *inquire_membuf;
char *hello_line;
char *okay_line; /* See assuan_set_okay_line() */
void *user_pointer; /* For assuan_get_pointer and assuan_set_pointer (). */
FILE *log_fp;
struct {
assuan_fd_t fd;
int eof;
char line[LINELENGTH];
int linelen; /* w/o CR, LF - might not be the same as
strlen(line) due to embedded nuls. However a nul
is always written at this pos. */
struct {
char line[LINELENGTH];
int linelen ;
int pending; /* i.e. at least one line is available in the attic */
} attic;
} inbound;
struct {
assuan_fd_t fd;
struct {
FILE *fp;
char line[LINELENGTH];
int linelen;
int error;
} data;
} outbound;
int pipe_mode; /* We are in pipe mode, i.e. we can handle just one
connection and must terminate then. */
pid_t pid; /* The pid of the peer. */
assuan_fd_t listen_fd; /* The fd we are listening on (used by
socket servers) */
assuan_sock_nonce_t listen_nonce; /* Used with LISTEN_FD. */
assuan_fd_t connected_fd; /* helper */
struct {
int valid; /* Whether this structure has valid information. */
#ifdef HAVE_SO_PEERCRED
pid_t pid; /* The pid of the peer. */
uid_t uid; /* The uid of the peer. */
gid_t gid; /* The gid of the peer. */
#endif /* HAVE_SO_PEERCRED */
} peercred;
/* Used for Unix domain sockets. */
struct sockaddr_un myaddr;
struct sockaddr_un serveraddr;
/* Structure used for unix domain socket buffering. FIXME: We don't
use datagrams anymore thus we could get away with a simpler
buffering approach. */
struct {
void *buffer; /* Malloced buffer. */
int bufferallocated; /* Memory allocated. */
int bufferoffset; /* Offset of start of buffer. */
int buffersize; /* Bytes buffered. */
assuan_fd_t pendingfds[5]; /* Array to save received descriptors. */
int pendingfdscount; /* Number of received descriptors. */
} uds;
void (*deinit_handler)(assuan_context_t);
int (*accept_handler)(assuan_context_t);
int (*finish_handler)(assuan_context_t);
struct cmdtbl_s *cmdtbl;
size_t cmdtbl_used; /* used entries */
size_t cmdtbl_size; /* allocated size of table */
void (*bye_notify_fnc)(assuan_context_t);
void (*reset_notify_fnc)(assuan_context_t);
void (*cancel_notify_fnc)(assuan_context_t);
int (*option_handler_fnc)(assuan_context_t,const char*, const char*);
void (*input_notify_fnc)(assuan_context_t, const char *);
void (*output_notify_fnc)(assuan_context_t, const char *);
/* This function is called right after a command has been processed.
It may be used to command related cleanup. */
void (*post_cmd_notify_fnc)(assuan_context_t, int);
/* If set, this is called right before logging an I/O line. With
DIRECTION set to 1 it is called for an output oeration; 0 means
an input operation. If bit 0 is set in the return value, the
logging of the line will be suppressed. With bit 1 set, the
entire line will be ignored. */
unsigned int (*io_monitor)(assuan_context_t ctx,
int direction,
const char *line,
size_t linelen);
assuan_fd_t input_fd; /* Set by the INPUT command. */
assuan_fd_t output_fd; /* Set by the OUTPUT command. */
/* io routines. */
struct assuan_io *io;
};
/*-- assuan-pipe-server.c --*/
int _assuan_new_context (assuan_context_t *r_ctx);
void _assuan_release_context (assuan_context_t ctx);
/*-- assuan-uds.c --*/
void _assuan_uds_close_fds (assuan_context_t ctx);
void _assuan_uds_deinit (assuan_context_t ctx);
void _assuan_init_uds_io (assuan_context_t ctx);
/*-- assuan-handler.c --*/
int _assuan_register_std_commands (assuan_context_t ctx);
/*-- assuan-buffer.c --*/
assuan_error_t _assuan_read_line (assuan_context_t ctx);
int _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size);
int _assuan_cookie_write_flush (void *cookie);
assuan_error_t _assuan_write_line (assuan_context_t ctx, const char *prefix,
const char *line, size_t len);
/*-- assuan-client.c --*/
assuan_error_t _assuan_read_from_server (assuan_context_t ctx,
int *okay, int *off);
/*-- assuan-error.c --*/
/*-- assuan-inquire.c --*/
int _assuan_inquire_ext_cb (assuan_context_t ctx);
void _assuan_inquire_release (assuan_context_t ctx);
/* Map error codes as used in this implementation to the libgpg-error
codes. */
assuan_error_t _assuan_error (int oldcode);
/* Check if ERR means EAGAIN. */
int _assuan_error_is_eagain (assuan_error_t err);
/* Extract the error code from A. This works for both the old and the
new style error codes. This needs to be used whenever an error
code is compared. */
#define err_code(a) ((a) & 0x00ffffff)
/* Check whether A is the erro code for EOF. We allow for old and new
style EOF error codes here. */
#define err_is_eof(a) ((a) == (-1) || err_code (a) == 16383)
/*-- assuan-util.c --*/
void *_assuan_malloc (size_t n);
void *_assuan_calloc (size_t n, size_t m);
void *_assuan_realloc (void *p, size_t n);
void _assuan_free (void *p);
#define xtrymalloc(a) _assuan_malloc ((a))
#define xtrycalloc(a,b) _assuan_calloc ((a),(b))
#define xtryrealloc(a,b) _assuan_realloc((a),(b))
#define xfree(a) _assuan_free ((a))
#define set_error(c,e,t) \
assuan_set_error ((c), _assuan_error (ASSUAN_ ## e), (t))
#ifdef HAVE_W32_SYSTEM
const char *_assuan_w32_strerror (int ec);
#define w32_strerror(e) _assuan_w32_strerror ((e))
int _assuan_gpg_strerror_r (unsigned int err, char *buf, size_t buflen);
const char *_assuan_gpg_strsource (unsigned int err);
#endif /*HAVE_W32_SYSTEM*/
/*-- assuan-logging.c --*/
void _assuan_set_default_log_stream (FILE *fp);
void _assuan_log_printf (const char *format, ...)
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
__attribute__ ((format (printf,1,2)))
#endif
;
void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length);
void _assuan_log_sanitized_string (const char *string);
/*-- assuan-io.c --*/
pid_t _assuan_waitpid (pid_t pid, int *status, int options);
ssize_t _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size);
ssize_t _assuan_simple_write (assuan_context_t ctx, const void *buffer,
size_t size);
ssize_t _assuan_io_read (assuan_fd_t fd, void *buffer, size_t size);
ssize_t _assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size);
#ifdef HAVE_W32_SYSTEM
int _assuan_simple_sendmsg (assuan_context_t ctx, void *msg);
int _assuan_simple_recvmsg (assuan_context_t ctx, void *msg);
#else
ssize_t _assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg);
ssize_t _assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg);
#endif
void _assuan_usleep (unsigned int usec);
/*-- assuan-socket.c --*/
int _assuan_close (assuan_fd_t fd);
assuan_fd_t _assuan_sock_new (int domain, int type, int proto);
int _assuan_sock_connect (assuan_fd_t sockfd,
struct sockaddr *addr, int addrlen);
int _assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen);
int _assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,
assuan_sock_nonce_t *nonce);
int _assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce);
#ifdef HAVE_W32_SYSTEM
int _assuan_sock_wsa2errno (int err);
#endif
#ifdef HAVE_FOPENCOOKIE
/* We have to implement funopen in terms of glibc's fopencookie. */
FILE *_assuan_funopen(void *cookie,
cookie_read_function_t *readfn,
cookie_write_function_t *writefn,
cookie_seek_function_t *seekfn,
cookie_close_function_t *closefn);
#define funopen(a,r,w,s,c) _assuan_funopen ((a), (r), (w), (s), (c))
#endif /*HAVE_FOPENCOOKIE*/
/* Prototypes for replacement functions. */
#ifndef HAVE_MEMRCHR
void *memrchr (const void *block, int c, size_t size);
#endif
#ifndef HAVE_STPCPY
char *stpcpy (char *dest, const char *src);
#endif
#ifndef HAVE_SETENV
#define setenv _assuan_setenv
#define unsetenv _assuan_unsetenv
#define clearenv _assuan_clearenv
int setenv (const char *name, const char *value, int replace);
#endif
#ifndef HAVE_PUTC_UNLOCKED
int putc_unlocked (int c, FILE *stream);
#endif
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
#define DIMof(type,member) DIM(((type *)0)->member)
#if HAVE_W32_SYSTEM
#define SOCKET2HANDLE(s) ((void *)(s))
#define HANDLE2SOCKET(h) ((unsigned int)(h))
#else
#define SOCKET2HANDLE(s) (s)
#define HANDLE2SOCKET(h) (h)
#endif
#endif /*ASSUAN_DEFS_H*/

View File

@ -1,915 +0,0 @@
/* assuan-handler.c - dispatch commands
* Copyright (C) 2001, 2002, 2003, 2007 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "assuan-defs.h"
#define spacep(p) (*(p) == ' ' || *(p) == '\t')
#define digitp(a) ((a) >= '0' && (a) <= '9')
static int my_strcasecmp (const char *a, const char *b);
#define PROCESS_DONE(ctx, rc) \
((ctx)->in_process_next ? assuan_process_done ((ctx), (rc)) : (rc))
static int
dummy_handler (assuan_context_t ctx, char *line)
{
return
PROCESS_DONE (ctx, set_error (ctx, Server_Fault, "no handler registered"));
}
static int
std_handler_nop (assuan_context_t ctx, char *line)
{
return PROCESS_DONE (ctx, 0); /* okay */
}
static int
std_handler_cancel (assuan_context_t ctx, char *line)
{
if (ctx->cancel_notify_fnc)
ctx->cancel_notify_fnc (ctx);
return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL));
}
static int
std_handler_option (assuan_context_t ctx, char *line)
{
char *key, *value, *p;
for (key=line; spacep (key); key++)
;
if (!*key)
return
PROCESS_DONE (ctx, set_error (ctx, Syntax_Error, "argument required"));
if (*key == '=')
return
PROCESS_DONE (ctx, set_error (ctx, Syntax_Error,
"no option name given"));
for (value=key; *value && !spacep (value) && *value != '='; value++)
;
if (*value)
{
if (spacep (value))
*value++ = 0; /* terminate key */
for (; spacep (value); value++)
;
if (*value == '=')
{
*value++ = 0; /* terminate key */
for (; spacep (value); value++)
;
if (!*value)
return
PROCESS_DONE (ctx, set_error (ctx, Syntax_Error,
"option argument expected"));
}
if (*value)
{
for (p = value + strlen(value) - 1; p > value && spacep (p); p--)
;
if (p > value)
*++p = 0; /* strip trailing spaces */
}
}
if (*key == '-' && key[1] == '-' && key[2])
key += 2; /* the double dashes are optional */
if (*key == '-')
return PROCESS_DONE (ctx,
set_error (ctx, Syntax_Error,
"option should not begin with one dash"));
if (ctx->option_handler_fnc)
return PROCESS_DONE (ctx, ctx->option_handler_fnc (ctx, key, value));
return PROCESS_DONE (ctx, 0);
}
static int
std_handler_bye (assuan_context_t ctx, char *line)
{
if (ctx->bye_notify_fnc)
ctx->bye_notify_fnc (ctx);
assuan_close_input_fd (ctx);
assuan_close_output_fd (ctx);
return PROCESS_DONE (ctx, _assuan_error (-1)); /* pretty simple :-) */
}
static int
std_handler_auth (assuan_context_t ctx, char *line)
{
return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL));
}
static int
std_handler_reset (assuan_context_t ctx, char *line)
{
if (ctx->reset_notify_fnc)
ctx->reset_notify_fnc (ctx);
assuan_close_input_fd (ctx);
assuan_close_output_fd (ctx);
_assuan_uds_close_fds (ctx);
return PROCESS_DONE (ctx, 0);
}
static int
std_handler_help (assuan_context_t ctx, char *line)
{
unsigned int i;
char buf[ASSUAN_LINELENGTH];
for (i = 0; i < ctx->cmdtbl_used; i++)
{
snprintf (buf, sizeof (buf), "# %s", ctx->cmdtbl[i].name);
buf[ASSUAN_LINELENGTH - 1] = '\0';
assuan_write_line (ctx, buf);
}
return PROCESS_DONE (ctx, 0);
}
static int
std_handler_end (assuan_context_t ctx, char *line)
{
return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL));
}
assuan_error_t
assuan_command_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd)
{
char *endp;
if ((strncmp (line, "FD", 2) && strncmp (line, "fd", 2))
|| (line[2] != '=' && line[2] != '\0' && !spacep(&line[2])))
return set_error (ctx, Syntax_Error, "FD[=<n>] expected");
line += 2;
if (*line == '=')
{
line ++;
if (!digitp (*line))
return set_error (ctx, Syntax_Error, "number required");
#ifdef HAVE_W32_SYSTEM
/* Fixme: For a W32/64bit system we will need to change the cast
and the conversion fucntion. */
*rfd = (void*)strtoul (line, &endp, 10);
#else
*rfd = strtoul (line, &endp, 10);
#endif
/* Remove that argument so that a notify handler won't see it. */
memset (line, ' ', endp? (endp-line):strlen(line));
if (*rfd == ctx->inbound.fd)
return set_error (ctx, Parameter_Conflict, "fd same as inbound fd");
if (*rfd == ctx->outbound.fd)
return set_error (ctx, Parameter_Conflict, "fd same as outbound fd");
return 0;
}
else
/* Our peer has sent the file descriptor. */
return assuan_receivefd (ctx, rfd);
}
/* Format is INPUT FD=<n> */
static int
std_handler_input (assuan_context_t ctx, char *line)
{
int rc;
assuan_fd_t fd;
rc = assuan_command_parse_fd (ctx, line, &fd);
if (rc)
return PROCESS_DONE (ctx, rc);
ctx->input_fd = fd;
if (ctx->input_notify_fnc)
ctx->input_notify_fnc (ctx, line);
return PROCESS_DONE (ctx, 0);
}
/* Format is OUTPUT FD=<n> */
static int
std_handler_output (assuan_context_t ctx, char *line)
{
int rc;
assuan_fd_t fd;
rc = assuan_command_parse_fd (ctx, line, &fd);
if (rc)
return PROCESS_DONE (ctx, rc);
ctx->output_fd = fd;
if (ctx->output_notify_fnc)
ctx->output_notify_fnc (ctx, line);
return PROCESS_DONE (ctx, 0);
}
/* This is a table with the standard commands and handler for them.
The table is used to initialize a new context and associate strings
with default handlers */
static struct {
const char *name;
int (*handler)(assuan_context_t, char *line);
int always; /* always initialize this command */
} std_cmd_table[] = {
{ "NOP", std_handler_nop, 1 },
{ "CANCEL", std_handler_cancel, 1 },
{ "OPTION", std_handler_option, 1 },
{ "BYE", std_handler_bye, 1 },
{ "AUTH", std_handler_auth, 1 },
{ "RESET", std_handler_reset, 1 },
{ "END", std_handler_end, 1 },
{ "HELP", std_handler_help, 1 },
{ "INPUT", std_handler_input, 0 },
{ "OUTPUT", std_handler_output, 0 },
{ "OPTION", std_handler_option, 1 },
{ NULL, NULL, 0 }
};
/**
* assuan_register_command:
* @ctx: the server context
* @cmd_name: A string with the command name
* @handler: The handler function to be called or NULL to use a default
* handler.
*
* Register a handler to be used for a given command. Note that
* several default handlers are already regsitered with a new context.
* This function however allows to override them.
*
* Return value: 0 on success or an error code
**/
int
assuan_register_command (assuan_context_t ctx,
const char *cmd_name,
int (*handler)(assuan_context_t, char *))
{
int i;
const char *s;
if (cmd_name && !*cmd_name)
cmd_name = NULL;
if (!cmd_name)
return _assuan_error (ASSUAN_Invalid_Value);
if (!handler)
{ /* find a default handler. */
for (i=0; (s=std_cmd_table[i].name) && strcmp (cmd_name, s); i++)
;
if (!s)
{ /* Try again but case insensitive. */
for (i=0; (s=std_cmd_table[i].name)
&& my_strcasecmp (cmd_name, s); i++)
;
}
if (s)
handler = std_cmd_table[i].handler;
if (!handler)
handler = dummy_handler; /* Last resort is the dummy handler. */
}
if (!ctx->cmdtbl)
{
ctx->cmdtbl_size = 50;
ctx->cmdtbl = xtrycalloc ( ctx->cmdtbl_size, sizeof *ctx->cmdtbl);
if (!ctx->cmdtbl)
return _assuan_error (ASSUAN_Out_Of_Core);
ctx->cmdtbl_used = 0;
}
else if (ctx->cmdtbl_used >= ctx->cmdtbl_size)
{
struct cmdtbl_s *x;
x = xtryrealloc ( ctx->cmdtbl, (ctx->cmdtbl_size+10) * sizeof *x);
if (!x)
return _assuan_error (ASSUAN_Out_Of_Core);
ctx->cmdtbl = x;
ctx->cmdtbl_size += 50;
}
ctx->cmdtbl[ctx->cmdtbl_used].name = cmd_name;
ctx->cmdtbl[ctx->cmdtbl_used].handler = handler;
ctx->cmdtbl_used++;
return 0;
}
int
assuan_register_post_cmd_notify (assuan_context_t ctx,
void (*fnc)(assuan_context_t, int))
{
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
ctx->post_cmd_notify_fnc = fnc;
return 0;
}
int
assuan_register_bye_notify (assuan_context_t ctx,
void (*fnc)(assuan_context_t))
{
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
ctx->bye_notify_fnc = fnc;
return 0;
}
int
assuan_register_reset_notify (assuan_context_t ctx,
void (*fnc)(assuan_context_t))
{
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
ctx->reset_notify_fnc = fnc;
return 0;
}
int
assuan_register_cancel_notify (assuan_context_t ctx,
void (*fnc)(assuan_context_t))
{
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
ctx->cancel_notify_fnc = fnc;
return 0;
}
int
assuan_register_option_handler (assuan_context_t ctx,
int (*fnc)(assuan_context_t,
const char*, const char*))
{
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
ctx->option_handler_fnc = fnc;
return 0;
}
int
assuan_register_input_notify (assuan_context_t ctx,
void (*fnc)(assuan_context_t, const char *))
{
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
ctx->input_notify_fnc = fnc;
return 0;
}
int
assuan_register_output_notify (assuan_context_t ctx,
void (*fnc)(assuan_context_t, const char *))
{
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
ctx->output_notify_fnc = fnc;
return 0;
}
/* Helper to register the standards commands */
int
_assuan_register_std_commands (assuan_context_t ctx)
{
int i, rc;
for (i=0; std_cmd_table[i].name; i++)
{
if (std_cmd_table[i].always)
{
rc = assuan_register_command (ctx, std_cmd_table[i].name, NULL);
if (rc)
return rc;
}
}
return 0;
}
/* Process the special data lines. The "D " has already been removed
from the line. As all handlers this function may modify the line. */
static int
handle_data_line (assuan_context_t ctx, char *line, int linelen)
{
return set_error (ctx, Not_Implemented, NULL);
}
/* like ascii_strcasecmp but assume that B is already uppercase */
static int
my_strcasecmp (const char *a, const char *b)
{
if (a == b)
return 0;
for (; *a && *b; a++, b++)
{
if (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) != *b)
break;
}
return *a == *b? 0 : (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) - *b);
}
/* Parse the line, break out the command, find it in the command
table, remove leading and white spaces from the arguments, call the
handler with the argument line and return the error. */
static int
dispatch_command (assuan_context_t ctx, char *line, int linelen)
{
char *p;
const char *s;
int shift, i;
/* Note that as this function is invoked by assuan_process_next as
well, we need to hide non-critical errors with PROCESS_DONE. */
if (*line == 'D' && line[1] == ' ') /* divert to special handler */
/* FIXME: Depending on the final implementation of
handle_data_line, this may be wrong here. For example, if a
user callback is invoked, and that callback is responsible for
calling assuan_process_done, then this is wrong. */
return PROCESS_DONE (ctx, handle_data_line (ctx, line+2, linelen-2));
for (p=line; *p && *p != ' ' && *p != '\t'; p++)
;
if (p==line)
return PROCESS_DONE
(ctx, set_error (ctx, Syntax_Error, "leading white-space"));
if (*p)
{ /* Skip over leading WS after the keyword */
*p++ = 0;
while ( *p == ' ' || *p == '\t')
p++;
}
shift = p - line;
for (i=0; (s=ctx->cmdtbl[i].name); i++)
{
if (!strcmp (line, s))
break;
}
if (!s)
{ /* and try case insensitive */
for (i=0; (s=ctx->cmdtbl[i].name); i++)
{
if (!my_strcasecmp (line, s))
break;
}
}
if (!s)
return PROCESS_DONE (ctx, set_error (ctx, Unknown_Command, NULL));
line += shift;
linelen -= shift;
/* fprintf (stderr, "DBG-assuan: processing %s `%s'\n", s, line); */
return ctx->cmdtbl[i].handler (ctx, line);
}
/* Call this to acknowledge the current command. */
int
assuan_process_done (assuan_context_t ctx, int rc)
{
if (!ctx->in_command)
return _assuan_error (ASSUAN_General_Error);
ctx->in_command = 0;
/* Check for data write errors. */
if (ctx->outbound.data.fp)
{
/* Flush the data lines. */
fclose (ctx->outbound.data.fp);
ctx->outbound.data.fp = NULL;
if (!rc && ctx->outbound.data.error)
rc = ctx->outbound.data.error;
}
else
{
/* Flush any data send without using the data FP. */
assuan_send_data (ctx, NULL, 0);
if (!rc && ctx->outbound.data.error)
rc = ctx->outbound.data.error;
}
/* Error handling. */
if (!rc)
{
rc = assuan_write_line (ctx, ctx->okay_line? ctx->okay_line : "OK");
}
else if (err_is_eof (rc))
{ /* No error checking because the peer may have already disconnect. */
assuan_write_line (ctx, "OK closing connection");
ctx->finish_handler (ctx);
}
else
{
char errline[300];
if (rc < 100)
sprintf (errline, "ERR %d server fault (%.50s)",
_assuan_error (ASSUAN_Server_Fault), assuan_strerror (rc));
else
{
const char *text = ctx->err_no == rc? ctx->err_str:NULL;
#if defined(HAVE_W32_SYSTEM)
unsigned int source, code;
char ebuf[50];
const char *esrc;
source = ((rc >> 24) & 0xff);
code = (rc & 0x00ffffff);
if (source
&& !_assuan_gpg_strerror_r (rc, ebuf, sizeof ebuf)
&& (esrc=_assuan_gpg_strsource (rc)))
{
/* Assume this is an libgpg-error. */
sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s",
rc, ebuf, esrc,
text? " - ":"", text?text:"");
}
else
#elif defined(__GNUC__) && defined(__ELF__)
/* If we have weak symbol support we try to use the error
strings from libgpg-error without creating a dependency.
They are used for debugging purposes only, so there is no
problem if they are not available. We need to make sure
that we are using ELF because only this guarantees that
weak symbol support is available in case GNU ld is not
used. It seems that old gcc versions don't implement the
weak attribute properly but it works with the weak
pragma. */
unsigned int source, code;
int gpg_strerror_r (unsigned int err, char *buf, size_t buflen)
__attribute__ ((weak));
const char *gpg_strsource (unsigned int err)
__attribute__ ((weak));
#if __GNUC__ < 3
#pragma weak gpg_strerror_r
#pragma weak gpg_strsource
#endif
source = ((rc >> 24) & 0xff);
code = (rc & 0x00ffffff);
if (source && gpg_strsource && gpg_strerror_r)
{
/* Assume this is an libgpg-error. */
char ebuf[50];
gpg_strerror_r (rc, ebuf, sizeof ebuf );
sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s",
rc,
ebuf,
gpg_strsource (rc),
text? " - ":"", text?text:"");
}
else
#endif /* __GNUC__ && __ELF__ */
sprintf (errline, "ERR %d %.50s%s%.100s",
rc, assuan_strerror (rc), text? " - ":"", text?text:"");
}
rc = assuan_write_line (ctx, errline);
}
if (ctx->post_cmd_notify_fnc)
ctx->post_cmd_notify_fnc (ctx, rc);
ctx->confidential = 0;
if (ctx->okay_line)
{
xfree (ctx->okay_line);
ctx->okay_line = NULL;
}
return rc;
}
static int
process_next (assuan_context_t ctx)
{
int rc;
/* What the next thing to do is depends on the current state.
However, we will always first read the next line. The client is
required to write full lines without blocking long after starting
a partial line. */
rc = _assuan_read_line (ctx);
if (rc)
return rc;
if (*ctx->inbound.line == '#' || !ctx->inbound.linelen)
/* Comment lines are ignored. */
return 0;
/* Now we have a line that really means something. It could be one
of the following things: First, if we are not in a command
already, it is the next command to dispatch. Second, if we are
in a command, it can only be the response to an INQUIRE
reply. */
if (!ctx->in_command)
{
ctx->in_command = 1;
ctx->outbound.data.error = 0;
ctx->outbound.data.linelen = 0;
/* Dispatch command and return reply. */
ctx->in_process_next = 1;
rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen);
ctx->in_process_next = 0;
}
else if (ctx->in_inquire)
{
/* FIXME: Pick up the continuation. */
rc = _assuan_inquire_ext_cb (ctx);
}
else
{
/* Should not happen. The client is sending data while we are
in a command and not waiting for an inquire. We log an error
and discard it. */
_assuan_log_printf ("unexpected client data\n");
rc = 0;
}
return rc;
}
/* This function should be invoked when the assuan connected FD is
ready for reading. If the equivalent to EWOULDBLOCK is returned
(this should be done by the command handler), assuan_process_next
should be invoked the next time the connected FD is readable.
Eventually, the caller will finish by invoking
assuan_process_done. */
int
assuan_process_next (assuan_context_t ctx)
{
int rc;
do
{
rc = process_next (ctx);
}
while (!rc && assuan_pending_line (ctx));
return rc;
}
static int
process_request (assuan_context_t ctx)
{
int rc;
if (ctx->in_inquire)
return _assuan_error (ASSUAN_Nested_Commands);
do
{
rc = _assuan_read_line (ctx);
}
while (_assuan_error_is_eagain (rc));
if (rc)
return rc;
if (*ctx->inbound.line == '#' || !ctx->inbound.linelen)
return 0; /* comment line - ignore */
ctx->in_command = 1;
ctx->outbound.data.error = 0;
ctx->outbound.data.linelen = 0;
/* dispatch command and return reply */
rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen);
return assuan_process_done (ctx, rc);
}
/**
* assuan_process:
* @ctx: assuan context
*
* This function is used to handle the assuan protocol after a
* connection has been established using assuan_accept(). This is the
* main protocol handler.
*
* Return value: 0 on success or an error code if the assuan operation
* failed. Note, that no error is returned for operational errors.
**/
int
assuan_process (assuan_context_t ctx)
{
int rc;
do {
rc = process_request (ctx);
} while (!rc);
if (err_is_eof (rc))
rc = 0;
return rc;
}
/**
* assuan_get_active_fds:
* @ctx: Assuan context
* @what: 0 for read fds, 1 for write fds
* @fdarray: Caller supplied array to store the FDs
* @fdarraysize: size of that array
*
* Return all active filedescriptors for the given context. This
* function can be used to select on the fds and call
* assuan_process_next() if there is an active one. The first fd in
* the array is the one used for the command connection.
*
* Note, that write FDs are not yet supported.
*
* Return value: number of FDs active and put into @fdarray or -1 on
* error which is most likely a too small fdarray.
**/
int
assuan_get_active_fds (assuan_context_t ctx, int what,
assuan_fd_t *fdarray, int fdarraysize)
{
int n = 0;
if (!ctx || fdarraysize < 2 || what < 0 || what > 1)
return -1;
if (!what)
{
if (ctx->inbound.fd != ASSUAN_INVALID_FD)
fdarray[n++] = ctx->inbound.fd;
}
else
{
if (ctx->outbound.fd != ASSUAN_INVALID_FD)
fdarray[n++] = ctx->outbound.fd;
if (ctx->outbound.data.fp)
#ifdef HAVE_W32_SYSTEM
fdarray[n++] = (void*)_get_osfhandle (fileno (ctx->outbound.data.fp));
#else
fdarray[n++] = fileno (ctx->outbound.data.fp);
#endif
}
return n;
}
/* Two simple wrappers to make the expected function types match. */
#ifdef HAVE_FUNOPEN
static int
fun1_cookie_write (void *cookie, const char *buffer, int orig_size)
{
return _assuan_cookie_write_data (cookie, buffer, orig_size);
}
#endif /*HAVE_FUNOPEN*/
#ifdef HAVE_FOPENCOOKIE
static ssize_t
fun2_cookie_write (void *cookie, const char *buffer, size_t orig_size)
{
return _assuan_cookie_write_data (cookie, buffer, orig_size);
}
#endif /*HAVE_FOPENCOOKIE*/
/* Return a FP to be used for data output. The FILE pointer is valid
until the end of a handler. So a close is not needed. Assuan does
all the buffering needed to insert the status line as well as the
required line wappping and quoting for data lines.
We use GNU's custom streams here. There should be an alternative
implementaion for systems w/o a glibc, a simple implementation
could use a child process */
FILE *
assuan_get_data_fp (assuan_context_t ctx)
{
#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
if (ctx->outbound.data.fp)
return ctx->outbound.data.fp;
#ifdef HAVE_FUNOPEN
ctx->outbound.data.fp = funopen (ctx, 0, fun1_cookie_write,
0, _assuan_cookie_write_flush);
#else
ctx->outbound.data.fp = funopen (ctx, 0, fun2_cookie_write,
0, _assuan_cookie_write_flush);
#endif
ctx->outbound.data.error = 0;
return ctx->outbound.data.fp;
#else
errno = ENOSYS;
return NULL;
#endif
}
/* Set the text used for the next OK reponse. This string is
automatically reset to NULL after the next command. */
assuan_error_t
assuan_set_okay_line (assuan_context_t ctx, const char *line)
{
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
if (!line)
{
xfree (ctx->okay_line);
ctx->okay_line = NULL;
}
else
{
/* FIXME: we need to use gcry_is_secure() to test whether
we should allocate the entire line in secure memory */
char *buf = xtrymalloc (3+strlen(line)+1);
if (!buf)
return _assuan_error (ASSUAN_Out_Of_Core);
strcpy (buf, "OK ");
strcpy (buf+3, line);
xfree (ctx->okay_line);
ctx->okay_line = buf;
}
return 0;
}
assuan_error_t
assuan_write_status (assuan_context_t ctx,
const char *keyword, const char *text)
{
char buffer[256];
char *helpbuf;
size_t n;
assuan_error_t ae;
if ( !ctx || !keyword)
return _assuan_error (ASSUAN_Invalid_Value);
if (!text)
text = "";
n = 2 + strlen (keyword) + 1 + strlen (text) + 1;
if (n < sizeof (buffer))
{
strcpy (buffer, "S ");
strcat (buffer, keyword);
if (*text)
{
strcat (buffer, " ");
strcat (buffer, text);
}
ae = assuan_write_line (ctx, buffer);
}
else if ( (helpbuf = xtrymalloc (n)) )
{
strcpy (helpbuf, "S ");
strcat (helpbuf, keyword);
if (*text)
{
strcat (helpbuf, " ");
strcat (helpbuf, text);
}
ae = assuan_write_line (ctx, helpbuf);
xfree (helpbuf);
}
else
ae = 0;
return ae;
}

View File

@ -1,385 +0,0 @@
/* assuan-inquire.c - handle inquire stuff
* Copyright (C) 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "assuan-defs.h"
#define digitp(a) ((a) >= '0' && (a) <= '9')
#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
*(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
struct membuf
{
size_t len;
size_t size;
char *buf;
int out_of_core;
int too_large;
size_t maxlen;
};
/* A simple implementation of a dynamic buffer. Use init_membuf() to
create a buffer, put_membuf to append bytes and get_membuf to
release and return the buffer. Allocation errors are detected but
only returned at the final get_membuf(), this helps not to clutter
the code with out of core checks. */
static void
init_membuf (struct membuf *mb, int initiallen, size_t maxlen)
{
mb->len = 0;
mb->size = initiallen;
mb->out_of_core = 0;
mb->too_large = 0;
mb->maxlen = maxlen;
/* we need to allocate one byte more for get_membuf */
mb->buf = xtrymalloc (initiallen+1);
if (!mb->buf)
mb->out_of_core = 1;
}
static void
put_membuf (struct membuf *mb, const void *buf, size_t len)
{
if (mb->out_of_core || mb->too_large)
return;
if (mb->maxlen && mb->len + len > mb->maxlen)
{
mb->too_large = 1;
return;
}
if (mb->len + len >= mb->size)
{
char *p;
mb->size += len + 1024;
/* we need to allocate one byte more for get_membuf */
p = xtryrealloc (mb->buf, mb->size+1);
if (!p)
{
mb->out_of_core = 1;
return;
}
mb->buf = p;
}
memcpy (mb->buf + mb->len, buf, len);
mb->len += len;
}
static void *
get_membuf (struct membuf *mb, size_t *len)
{
char *p;
if (mb->out_of_core || mb->too_large)
{
xfree (mb->buf);
mb->buf = NULL;
return NULL;
}
mb->buf[mb->len] = 0; /* there is enough space for the hidden eos */
p = mb->buf;
*len = mb->len;
mb->buf = NULL;
mb->out_of_core = 1; /* don't allow a reuse */
return p;
}
static void
free_membuf (struct membuf *mb)
{
xfree (mb->buf);
mb->buf = NULL;
}
/**
* assuan_inquire:
* @ctx: An assuan context
* @keyword: The keyword used for the inquire
* @r_buffer: Returns an allocated buffer
* @r_length: Returns the length of this buffer
* @maxlen: If not 0, the size limit of the inquired data.
*
* A Server may use this to Send an inquire. r_buffer, r_length and
* maxlen may all be NULL/0 to indicate that no real data is expected.
*
* Return value: 0 on success or an ASSUAN error code
**/
assuan_error_t
assuan_inquire (assuan_context_t ctx, const char *keyword,
unsigned char **r_buffer, size_t *r_length, size_t maxlen)
{
assuan_error_t rc;
struct membuf mb;
char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */
unsigned char *line, *p;
int linelen;
int nodataexpected;
if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
return _assuan_error (ASSUAN_Invalid_Value);
nodataexpected = !r_buffer && !r_length && !maxlen;
if (!nodataexpected && (!r_buffer || !r_length))
return _assuan_error (ASSUAN_Invalid_Value);
if (!ctx->is_server)
return _assuan_error (ASSUAN_Not_A_Server);
if (ctx->in_inquire)
return _assuan_error (ASSUAN_Nested_Commands);
ctx->in_inquire = 1;
if (nodataexpected)
memset (&mb, 0, sizeof mb); /* avoid compiler warnings */
else
init_membuf (&mb, maxlen? maxlen:1024, maxlen);
strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword);
rc = assuan_write_line (ctx, cmdbuf);
if (rc)
goto leave;
for (;;)
{
do
{
rc = _assuan_read_line (ctx);
if (rc)
goto leave;
line = (unsigned char *) ctx->inbound.line;
linelen = ctx->inbound.linelen;
}
while (*line == '#' || !linelen);
if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
&& (!line[3] || line[3] == ' '))
break; /* END command received*/
if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N')
{
rc = _assuan_error (ASSUAN_Canceled);
goto leave;
}
if (line[0] != 'D' || line[1] != ' ' || nodataexpected)
{
rc = _assuan_error (ASSUAN_Unexpected_Command);
goto leave;
}
if (linelen < 3)
continue;
line += 2;
linelen -= 2;
p = line;
while (linelen)
{
for (;linelen && *p != '%'; linelen--, p++)
;
put_membuf (&mb, line, p-line);
if (linelen > 2)
{ /* handle escaping */
unsigned char tmp[1];
p++;
*tmp = xtoi_2 (p);
p += 2;
linelen -= 3;
put_membuf (&mb, tmp, 1);
}
line = p;
}
if (mb.too_large)
{
rc = _assuan_error (ASSUAN_Too_Much_Data);
goto leave;
}
}
if (!nodataexpected)
{
*r_buffer = get_membuf (&mb, r_length);
if (!*r_buffer)
rc = _assuan_error (ASSUAN_Out_Of_Core);
}
leave:
if (!nodataexpected)
free_membuf (&mb);
ctx->in_inquire = 0;
return rc;
}
void
_assuan_inquire_release (assuan_context_t ctx)
{
if (ctx->in_inquire)
{
if (ctx->inquire_membuf)
{
free_membuf (ctx->inquire_membuf);
free (ctx->inquire_membuf);
}
ctx->in_inquire = 0;
}
}
int
_assuan_inquire_ext_cb (assuan_context_t ctx)
{
int rc;
unsigned char *line;
int linelen;
struct membuf *mb;
unsigned char *p;
line = (unsigned char *) ctx->inbound.line;
linelen = ctx->inbound.linelen;
mb = ctx->inquire_membuf;
if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N')
{
rc = _assuan_error (ASSUAN_Canceled);
goto leave;
}
if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
&& (!line[3] || line[3] == ' '))
{
rc = 0;
goto leave;
}
if (line[0] != 'D' || line[1] != ' ' || mb == NULL)
{
rc = _assuan_error (ASSUAN_Unexpected_Command);
goto leave;
}
if (linelen < 3)
return 0;
line += 2;
linelen -= 2;
p = line;
while (linelen)
{
for (;linelen && *p != '%'; linelen--, p++)
;
put_membuf (mb, line, p-line);
if (linelen > 2)
{ /* handle escaping */
unsigned char tmp[1];
p++;
*tmp = xtoi_2 (p);
p += 2;
linelen -= 3;
put_membuf (mb, tmp, 1);
}
line = p;
}
if (mb->too_large)
{
rc = _assuan_error (ASSUAN_Too_Much_Data);
goto leave;
}
return 0;
leave:
{
size_t buf_len = 0;
unsigned char *buf = NULL;
if (mb)
{
buf = get_membuf (mb, &buf_len);
if (!buf)
rc = _assuan_error (ASSUAN_Out_Of_Core);
free_membuf (mb);
free (mb);
ctx->inquire_membuf = NULL;
}
ctx->in_inquire = 0;
rc = (ctx->inquire_cb) (ctx->inquire_cb_data, rc, buf, buf_len);
}
return rc;
}
/**
* assuan_inquire_ext:
* @ctx: An assuan context
* @keyword: The keyword used for the inquire
* @maxlen: If not 0, the size limit of the inquired data.
* @cb: A callback handler which is invoked after the operation completed.
* @cb_data: A user-provided value passed to the callback handler.
*
* A Server may use this to Send an inquire. r_buffer, r_length and
* maxlen may all be NULL/0 to indicate that no real data is expected.
* When this function returns,
*
* Return value: 0 on success or an ASSUAN error code
**/
assuan_error_t
assuan_inquire_ext (assuan_context_t ctx, const char *keyword, size_t maxlen,
int (*cb) (void *cb_data, int rc, unsigned char *buf,
size_t len),
void *cb_data)
{
assuan_error_t rc;
struct membuf *mb = NULL;
char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */
if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
return _assuan_error (ASSUAN_Invalid_Value);
if (!ctx->is_server)
return _assuan_error (ASSUAN_Not_A_Server);
if (ctx->in_inquire)
return _assuan_error (ASSUAN_Nested_Commands);
mb = malloc (sizeof (struct membuf));
if (!mb)
return _assuan_error (ASSUAN_Out_Of_Core);
init_membuf (mb, maxlen ? maxlen : 1024, maxlen);
strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword);
rc = assuan_write_line (ctx, cmdbuf);
if (rc)
{
free_membuf (mb);
free (mb);
return rc;
}
ctx->in_inquire = 1;
/* Set up the continuation. */
ctx->inquire_cb = cb;
ctx->inquire_cb_data = cb_data;
ctx->inquire_membuf = mb;
return 0;
}

View File

@ -1,245 +0,0 @@
/* assuan-io.c - Wraps the read and write functions.
* Copyright (C) 2002, 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#include <unistd.h>
#include <errno.h>
#ifdef HAVE_W32_SYSTEM
# include <windows.h>
#else
# include <sys/wait.h>
#endif
#include "assuan-defs.h"
#ifndef HAVE_W32_SYSTEM
pid_t
_assuan_waitpid (pid_t pid, int *status, int options)
{
return waitpid (pid, status, options);
}
#endif
static ssize_t
do_io_read (assuan_fd_t fd, void *buffer, size_t size)
{
#if defined(HAVE_W32_SYSTEM) && !defined(_ASSUAN_IN_GPGME_BUILD_ASSUAN)
/* Due to the peculiarities of the W32 API we can't use read for a
network socket and thus we try to use recv first and fallback to
read if recv detects that it is not a network socket. */
int n;
n = recv (HANDLE2SOCKET(fd), buffer, size, 0);
if (n == -1)
{
switch (WSAGetLastError ())
{
case WSAENOTSOCK:
{
DWORD nread = 0;
n = ReadFile (fd, buffer, size, &nread, NULL);
if (!n)
{
switch (GetLastError())
{
case ERROR_BROKEN_PIPE: errno = EPIPE; break;
default: errno = EIO;
}
n = -1;
}
else
n = (int)nread;
}
break;
case WSAEWOULDBLOCK: errno = EAGAIN; break;
case ERROR_BROKEN_PIPE: errno = EPIPE; break;
default: errno = EIO; break;
}
}
return n;
#else /*!HAVE_W32_SYSTEM*/
return read (fd, buffer, size);
#endif /*!HAVE_W32_SYSTEM*/
}
ssize_t
_assuan_io_read (assuan_fd_t fd, void *buffer, size_t size)
{
ssize_t retval;
if (_assuan_io_hooks.read_hook
&& _assuan_io_hooks.read_hook (NULL, fd, buffer, size, &retval) == 1)
return retval;
return do_io_read (fd, buffer, size);
}
ssize_t
_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size)
{
ssize_t retval;
if (_assuan_io_hooks.read_hook
&& _assuan_io_hooks.read_hook (ctx, ctx->inbound.fd,
buffer, size, &retval) == 1)
return retval;
return do_io_read (ctx->inbound.fd, buffer, size);
}
static ssize_t
do_io_write (assuan_fd_t fd, const void *buffer, size_t size)
{
#if defined(HAVE_W32_SYSTEM) && !defined(_ASSUAN_IN_GPGME_BUILD_ASSUAN)
/* Due to the peculiarities of the W32 API we can't use write for a
network socket and thus we try to use send first and fallback to
write if send detects that it is not a network socket. */
int n;
n = send (HANDLE2SOCKET(fd), buffer, size, 0);
if (n == -1 && WSAGetLastError () == WSAENOTSOCK)
{
DWORD nwrite;
n = WriteFile (fd, buffer, size, &nwrite, NULL);
if (!n)
{
switch (GetLastError ())
{
case ERROR_BROKEN_PIPE:
case ERROR_NO_DATA: errno = EPIPE; break;
default: errno = EIO; break;
}
n = -1;
}
else
n = (int)nwrite;
}
return n;
#else /*!HAVE_W32_SYSTEM*/
return write (fd, buffer, size);
#endif /*!HAVE_W32_SYSTEM*/
}
ssize_t
_assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size)
{
ssize_t retval;
if (_assuan_io_hooks.write_hook
&& _assuan_io_hooks.write_hook (NULL, fd, buffer, size, &retval) == 1)
return retval;
return do_io_write (fd, buffer, size);
}
ssize_t
_assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)
{
ssize_t retval;
if (_assuan_io_hooks.write_hook
&& _assuan_io_hooks.write_hook (ctx, ctx->outbound.fd,
buffer, size, &retval) == 1)
return retval;
return do_io_write (ctx->outbound.fd, buffer, size);
}
#ifdef HAVE_W32_SYSTEM
int
_assuan_simple_sendmsg (assuan_context_t ctx, void *msg)
#else
ssize_t
_assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg)
#endif
{
#ifdef HAVE_W32_SYSTEM
return _assuan_error (ASSUAN_Not_Implemented);
#else
int ret;
while ( (ret = sendmsg (ctx->outbound.fd, msg, 0)) == -1 && errno == EINTR)
;
return ret;
#endif
}
#ifdef HAVE_W32_SYSTEM
int
_assuan_simple_recvmsg (assuan_context_t ctx, void *msg)
#else
ssize_t
_assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg)
#endif
{
#ifdef HAVE_W32_SYSTEM
return _assuan_error (ASSUAN_Not_Implemented);
#else
int ret;
while ( (ret = recvmsg (ctx->inbound.fd, msg, 0)) == -1 && errno == EINTR)
;
return ret;
#endif
}
void
_assuan_usleep (unsigned int usec)
{
if (usec)
{
#ifdef HAVE_NANOSLEEP
struct timespec req;
struct timespec rem;
req.tv_sec = 0;
req.tv_nsec = usec * 1000;
while (nanosleep (&req, &rem) < 0 && errno == EINTR)
req = rem;
#elif defined(HAVE_W32_SYSTEM)
Sleep (usec / 1000);
#else
struct timeval tv;
tv.tv_sec = usec / 1000000;
tv.tv_usec = usec % 1000000;
select (0, NULL, NULL, NULL, &tv);
#endif
}
}

View File

@ -1,155 +0,0 @@
/* assuan-listen.c - Wait for a connection (server)
* Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "assuan-defs.h"
assuan_error_t
assuan_set_hello_line (assuan_context_t ctx, const char *line)
{
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
if (!line)
{
xfree (ctx->hello_line);
ctx->hello_line = NULL;
}
else
{
char *buf = xtrymalloc (3+strlen(line)+1);
if (!buf)
return _assuan_error (ASSUAN_Out_Of_Core);
if (strchr (line, '\n'))
strcpy (buf, line);
else
{
strcpy (buf, "OK ");
strcpy (buf+3, line);
}
xfree (ctx->hello_line);
ctx->hello_line = buf;
}
return 0;
}
/**
* assuan_accept:
* @ctx: context
*
* Cancel any existing connection and wait for a connection from a
* client. The initial handshake is performed which may include an
* initial authentication or encryption negotiation.
*
* Return value: 0 on success or an error if the connection could for
* some reason not be established.
**/
assuan_error_t
assuan_accept (assuan_context_t ctx)
{
int rc;
const char *p, *pend;
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
if (ctx->pipe_mode > 1)
return -1; /* second invocation for pipemode -> terminate */
ctx->finish_handler (ctx);
rc = ctx->accept_handler (ctx);
if (rc)
return rc;
/* Send the hello. */
p = ctx->hello_line;
if (p && (pend = strchr (p, '\n')))
{ /* This is a multi line hello. Send all but the last line as
comments. */
do
{
rc = _assuan_write_line (ctx, "# ", p, pend - p);
if (rc)
return rc;
p = pend + 1;
pend = strchr (p, '\n');
}
while (pend);
rc = _assuan_write_line (ctx, "OK ", p, strlen (p));
}
else if (p)
rc = assuan_write_line (ctx, p);
else
rc = assuan_write_line (ctx, "OK Pleased to meet you");
if (rc)
return rc;
if (ctx->pipe_mode)
ctx->pipe_mode = 2;
return 0;
}
assuan_fd_t
assuan_get_input_fd (assuan_context_t ctx)
{
return ctx? ctx->input_fd : ASSUAN_INVALID_FD;
}
assuan_fd_t
assuan_get_output_fd (assuan_context_t ctx)
{
return ctx? ctx->output_fd : ASSUAN_INVALID_FD;
}
/* Close the fd descriptor set by the command INPUT FD=n. We handle
this fd inside assuan so that we can do some initial checks */
assuan_error_t
assuan_close_input_fd (assuan_context_t ctx)
{
if (!ctx || ctx->input_fd == ASSUAN_INVALID_FD)
return _assuan_error (ASSUAN_Invalid_Value);
_assuan_close (ctx->input_fd);
ctx->input_fd = ASSUAN_INVALID_FD;
return 0;
}
/* Close the fd descriptor set by the command OUTPUT FD=n. We handle
this fd inside assuan so that we can do some initial checks */
assuan_error_t
assuan_close_output_fd (assuan_context_t ctx)
{
if (!ctx || ctx->output_fd == ASSUAN_INVALID_FD)
return _assuan_error (ASSUAN_Invalid_Value);
_assuan_close (ctx->output_fd);
ctx->output_fd = ASSUAN_INVALID_FD;
return 0;
}

View File

@ -1,291 +0,0 @@
/* assuan-logging.c - Default logging function.
* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#ifdef HAVE_W32_SYSTEM
#include <windows.h>
#endif /*HAVE_W32_SYSTEM*/
#include <errno.h>
#include <ctype.h>
#include "assuan-defs.h"
static char prefix_buffer[80];
static FILE *_assuan_log;
static int full_logging;
void
_assuan_set_default_log_stream (FILE *fp)
{
if (!_assuan_log)
{
_assuan_log = fp;
full_logging = !!getenv ("ASSUAN_FULL_LOGGING");
}
}
void
assuan_set_assuan_log_stream (FILE *fp)
{
_assuan_log = fp;
}
/* Set the per context log stream. Also enable the default log stream
if it has not been set. */
void
assuan_set_log_stream (assuan_context_t ctx, FILE *fp)
{
if (ctx)
{
if (ctx->log_fp)
fflush (ctx->log_fp);
ctx->log_fp = fp;
_assuan_set_default_log_stream (fp);
}
}
FILE *
assuan_get_assuan_log_stream (void)
{
return _assuan_log ? _assuan_log : stderr;
}
/* Set the prefix to be used for logging to TEXT or
resets it to the default if TEXT is NULL. */
void
assuan_set_assuan_log_prefix (const char *text)
{
if (text)
{
strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1);
prefix_buffer[sizeof (prefix_buffer)-1] = 0;
}
else
*prefix_buffer = 0;
}
const char *
assuan_get_assuan_log_prefix (void)
{
return prefix_buffer;
}
void
_assuan_log_printf (const char *format, ...)
{
va_list arg_ptr;
FILE *fp;
const char *prf;
int save_errno = errno;
fp = assuan_get_assuan_log_stream ();
prf = assuan_get_assuan_log_prefix ();
if (*prf)
fprintf (fp, "%s[%u]: ", prf, (unsigned int)getpid ());
va_start (arg_ptr, format);
vfprintf (fp, format, arg_ptr );
va_end (arg_ptr);
/* If the log stream is a file, the output would be buffered. This
is bad for debugging, thus we flush the stream if FORMAT ends
with a LF. */
if (format && *format && format[strlen(format)-1] == '\n')
fflush (fp);
errno = save_errno;
}
/* Dump a possibly binary string (used for debugging). Distinguish
ascii text from binary and print it accordingly. This function
takes FILE pointer arg because logging may be enabled on a per
context basis. */
void
_assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length)
{
const unsigned char *s;
unsigned int n;
for (n = length, s = buffer; n; n--, s++)
if ((! isascii (*s) || iscntrl (*s) || ! isprint (*s)) && !(*s >= 0x80))
break;
s = buffer;
if (! n && *s != '[')
fwrite (buffer, length, 1, fp);
else
{
#ifdef HAVE_FLOCKFILE
flockfile (fp);
#endif
putc_unlocked ('[', fp);
if (length > 16 && ! full_logging)
{
for (n = 0; n < 12; n++, s++)
fprintf (fp, " %02x", *s);
fprintf (fp, " ...(%d bytes skipped)", (int) length - 12);
}
else
{
for (n = 0; n < length; n++, s++)
fprintf (fp, " %02x", *s);
}
putc_unlocked (' ', fp);
putc_unlocked (']', fp);
#ifdef HAVE_FUNLOCKFILE
funlockfile (fp);
#endif
}
}
/* Log a user supplied string. Escapes non-printable before
printing. */
void
_assuan_log_sanitized_string (const char *string)
{
const unsigned char *s = (const unsigned char *) string;
FILE *fp = assuan_get_assuan_log_stream ();
if (! *s)
return;
#ifdef HAVE_FLOCKFILE
flockfile (fp);
#endif
for (; *s; s++)
{
int c = 0;
switch (*s)
{
case '\r':
c = 'r';
break;
case '\n':
c = 'n';
break;
case '\f':
c = 'f';
break;
case '\v':
c = 'v';
break;
case '\b':
c = 'b';
break;
default:
if ((isascii (*s) && isprint (*s)) || (*s >= 0x80))
putc_unlocked (*s, fp);
else
{
putc_unlocked ('\\', fp);
fprintf (fp, "x%02x", *s);
}
}
if (c)
{
putc_unlocked ('\\', fp);
putc_unlocked (c, fp);
}
}
#ifdef HAVE_FUNLOCKFILE
funlockfile (fp);
#endif
}
#ifdef HAVE_W32_SYSTEM
const char *
_assuan_w32_strerror (int ec)
{
static char strerr[256];
if (ec == -1)
ec = (int)GetLastError ();
FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
strerr, sizeof (strerr)-1, NULL);
return strerr;
}
static int (*my_strerror_r) (unsigned int err, char *buf, size_t buflen);
static const char * (*my_strsource) (unsigned int err);
static int
load_libgpg_error (void)
{
/* This code is not race free but suitable for our purpose. */
static volatile int initialized;
void *handle;
if (initialized)
return (my_strerror_r && my_strsource)? 0:-1;
handle = LoadLibrary ("libgpg-error-0.dll");
if (handle)
{
void *foo, *bar;
foo = GetProcAddress (handle, "gpg_strerror_r");
bar = GetProcAddress (handle, "gpg_strsource");
if (foo && bar)
{
my_strerror_r = foo;
my_strsource = bar;
}
else
CloseHandle (handle);
}
initialized = 1;
return 0;
}
int
_assuan_gpg_strerror_r (unsigned int err, char *buf, size_t buflen)
{
if (load_libgpg_error ())
return -1;
return my_strerror_r (err, buf, buflen);
}
const char *
_assuan_gpg_strsource (unsigned int err)
{
if (load_libgpg_error ())
return NULL;
return my_strsource (err);
}
#endif /*HAVE_W32_SYSTEM*/

File diff suppressed because it is too large Load Diff

View File

@ -1,189 +0,0 @@
/* assuan-pipe-server.c - Assuan server working over a pipe
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#ifdef HAVE_W32_SYSTEM
#include <windows.h>
#include <fcntl.h>
#endif
#include "assuan-defs.h"
static void
deinit_pipe_server (assuan_context_t ctx)
{
/* nothing to do for this simple server */
}
static int
accept_connection (assuan_context_t ctx)
{
/* This is a NOP for a pipe server */
return 0;
}
static int
finish_connection (assuan_context_t ctx)
{
/* This is a NOP for a pipe server */
return 0;
}
/* Create a new context. Note that the handlers are set up for a pipe
server/client - this way we don't need extra dummy functions */
int
_assuan_new_context (assuan_context_t *r_ctx)
{
static struct assuan_io io = { _assuan_simple_read,
_assuan_simple_write,
0, 0 };
assuan_context_t ctx;
int rc;
*r_ctx = NULL;
ctx = xtrycalloc (1, sizeof *ctx);
if (!ctx)
return _assuan_error (ASSUAN_Out_Of_Core);
ctx->input_fd = ASSUAN_INVALID_FD;
ctx->output_fd = ASSUAN_INVALID_FD;
ctx->inbound.fd = ASSUAN_INVALID_FD;
ctx->outbound.fd = ASSUAN_INVALID_FD;
ctx->io = &io;
ctx->listen_fd = ASSUAN_INVALID_FD;
/* Use the pipe server handler as a default. */
ctx->deinit_handler = deinit_pipe_server;
ctx->accept_handler = accept_connection;
ctx->finish_handler = finish_connection;
rc = _assuan_register_std_commands (ctx);
if (rc)
xfree (ctx);
else
*r_ctx = ctx;
return rc;
}
/* Returns true if atoi(S) denotes a valid socket. */
#ifndef HAVE_W32_SYSTEM
static int
is_valid_socket (const char *s)
{
struct stat buf;
if ( fstat (atoi (s), &buf ) )
return 0;
return S_ISSOCK (buf.st_mode);
}
#endif /*!HAVE_W32_SYSTEM*/
int
assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2])
{
int rc;
rc = _assuan_new_context (r_ctx);
if (!rc)
{
assuan_context_t ctx = *r_ctx;
const char *s;
unsigned long ul;
ctx->is_server = 1;
#ifdef HAVE_W32_SYSTEM
/* MS Windows has so many different types of handle that one
needs to tranlsate them at many place forth and back. Also
make sure that the file descriptors are in binary mode. */
setmode (filedes[0], O_BINARY);
setmode (filedes[1], O_BINARY);
ctx->inbound.fd = (void*)_get_osfhandle (filedes[0]);
ctx->outbound.fd = (void*)_get_osfhandle (filedes[1]);
#else
s = getenv ("_assuan_connection_fd");
if (s && *s && is_valid_socket (s) )
{
/* Well, we are called with an bi-directional file
descriptor. Prepare for using sendmsg/recvmsg. In this
case we ignore the passed file descriptors. */
ctx->inbound.fd = ctx->outbound.fd = atoi (s);
_assuan_init_uds_io (ctx);
ctx->deinit_handler = _assuan_uds_deinit;
}
else if (filedes && filedes[0] != ASSUAN_INVALID_FD
&& filedes[1] != ASSUAN_INVALID_FD )
{
/* Standard pipe server. */
ctx->inbound.fd = filedes[0];
ctx->outbound.fd = filedes[1];
}
else
{
_assuan_release_context (*r_ctx);
*r_ctx = NULL;
return ASSUAN_Problem_Starting_Server;
}
#endif
ctx->pipe_mode = 1;
s = getenv ("_assuan_pipe_connect_pid");
if (s && (ul=strtoul (s, NULL, 10)) && ul)
ctx->pid = (pid_t)ul;
else
ctx->pid = (pid_t)-1;
}
return rc;
}
void
_assuan_release_context (assuan_context_t ctx)
{
if (ctx)
{
_assuan_inquire_release (ctx);
xfree (ctx->hello_line);
xfree (ctx->okay_line);
xfree (ctx->cmdtbl);
xfree (ctx);
}
}
void
assuan_deinit_server (assuan_context_t ctx)
{
if (ctx)
{
/* We use this function pointer to avoid linking other server
when not needed but still allow for a generic deinit function. */
ctx->deinit_handler (ctx);
ctx->deinit_handler = NULL;
_assuan_release_context (ctx);
}
}

View File

@ -1,180 +0,0 @@
/* assuan-socket-connect.c - Assuan socket based client
* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#ifndef HAVE_W32_SYSTEM
#include <sys/socket.h>
#include <sys/un.h>
#else
#include <windows.h>
#endif
#include "assuan-defs.h"
/* Hacks for Slowaris. */
#ifndef PF_LOCAL
# ifdef PF_UNIX
# define PF_LOCAL PF_UNIX
# else
# define PF_LOCAL AF_UNIX
# endif
#endif
#ifndef AF_LOCAL
# define AF_LOCAL AF_UNIX
#endif
#ifndef SUN_LEN
# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
+ strlen ((ptr)->sun_path))
#endif
static int
do_finish (assuan_context_t ctx)
{
if (ctx->inbound.fd != ASSUAN_INVALID_FD)
{
_assuan_close (ctx->inbound.fd);
}
ctx->inbound.fd = ASSUAN_INVALID_FD;
ctx->outbound.fd = ASSUAN_INVALID_FD;
return 0;
}
static void
do_deinit (assuan_context_t ctx)
{
do_finish (ctx);
}
/* Make a connection to the Unix domain socket NAME and return a new
Assuan context in CTX. SERVER_PID is currently not used but may
become handy in the future. */
assuan_error_t
assuan_socket_connect (assuan_context_t *r_ctx,
const char *name, pid_t server_pid)
{
return assuan_socket_connect_ext (r_ctx, name, server_pid, 0);
}
/* Make a connection to the Unix domain socket NAME and return a new
Assuan context in CTX. SERVER_PID is currently not used but may
become handy in the future. With flags set to 1 sendmsg and
recvmsg are used. */
assuan_error_t
assuan_socket_connect_ext (assuan_context_t *r_ctx,
const char *name, pid_t server_pid,
unsigned int flags)
{
static struct assuan_io io = { _assuan_simple_read, _assuan_simple_write,
NULL, NULL };
assuan_error_t err;
assuan_context_t ctx;
assuan_fd_t fd;
struct sockaddr_un srvr_addr;
size_t len;
const char *s;
if (!r_ctx || !name)
return _assuan_error (ASSUAN_Invalid_Value);
*r_ctx = NULL;
/* We require that the name starts with a slash, so that we
eventually can reuse this function for other socket types. To
make things easier we allow an optional driver prefix. */
s = name;
if (*s && s[1] == ':')
s += 2;
if (*s != DIRSEP_C && *s != '/')
return _assuan_error (ASSUAN_Invalid_Value);
if (strlen (name)+1 >= sizeof srvr_addr.sun_path)
return _assuan_error (ASSUAN_Invalid_Value);
err = _assuan_new_context (&ctx);
if (err)
return err;
ctx->deinit_handler = ((flags&1))? _assuan_uds_deinit : do_deinit;
ctx->finish_handler = do_finish;
fd = _assuan_sock_new (PF_LOCAL, SOCK_STREAM, 0);
if (fd == ASSUAN_INVALID_FD)
{
_assuan_log_printf ("can't create socket: %s\n", strerror (errno));
_assuan_release_context (ctx);
return _assuan_error (ASSUAN_General_Error);
}
memset (&srvr_addr, 0, sizeof srvr_addr);
srvr_addr.sun_family = AF_LOCAL;
strncpy (srvr_addr.sun_path, name, sizeof (srvr_addr.sun_path) - 1);
srvr_addr.sun_path[sizeof (srvr_addr.sun_path) - 1] = 0;
len = SUN_LEN (&srvr_addr);
if ( _assuan_sock_connect (fd, (struct sockaddr *) &srvr_addr, len) == -1 )
{
_assuan_log_printf ("can't connect to `%s': %s\n",
name, strerror (errno));
_assuan_release_context (ctx);
_assuan_close (fd);
return _assuan_error (ASSUAN_Connect_Failed);
}
ctx->inbound.fd = fd;
ctx->outbound.fd = fd;
ctx->io = &io;
if ((flags&1))
_assuan_init_uds_io (ctx);
/* initial handshake */
{
int okay, off;
err = _assuan_read_from_server (ctx, &okay, &off);
if (err)
_assuan_log_printf ("can't connect to server: %s\n",
assuan_strerror (err));
else if (okay != 1)
{
/*LOG ("can't connect to server: `");*/
_assuan_log_sanitized_string (ctx->inbound.line);
fprintf (assuan_get_assuan_log_stream (), "'\n");
err = _assuan_error (ASSUAN_Connect_Failed);
}
}
if (err)
{
assuan_disconnect (ctx);
}
else
*r_ctx = ctx;
return 0;
}

View File

@ -1,208 +0,0 @@
/* assuan-socket-server.c - Assuan socket based server
* Copyright (C) 2002, 2007 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#ifdef HAVE_W32_SYSTEM
# include <windows.h>
# if HAVE_SYS_SOCKET_H
# include <sys/socket.h>
# elif HAVE_WS2TCPIP_H
# include <ws2tcpip.h>
# endif
#else
# include <sys/socket.h>
# include <sys/un.h>
#endif
#include "assuan-defs.h"
static struct assuan_io io = { _assuan_simple_read, _assuan_simple_write,
NULL, NULL };
static int
accept_connection_bottom (assuan_context_t ctx)
{
assuan_fd_t fd = ctx->connected_fd;
ctx->peercred.valid = 0;
#ifdef HAVE_SO_PEERCRED
{
struct ucred cr;
socklen_t cl = sizeof cr;
if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
{
ctx->peercred.pid = cr.pid;
ctx->peercred.uid = cr.uid;
ctx->peercred.gid = cr.gid;
ctx->peercred.valid = 1;
/* This overrides any already set PID if the function returns
a valid one. */
if (cr.pid != (pid_t)-1 && cr.pid)
ctx->pid = cr.pid;
}
}
#endif
ctx->inbound.fd = fd;
ctx->inbound.eof = 0;
ctx->inbound.linelen = 0;
ctx->inbound.attic.linelen = 0;
ctx->inbound.attic.pending = 0;
ctx->outbound.fd = fd;
ctx->outbound.data.linelen = 0;
ctx->outbound.data.error = 0;
ctx->confidential = 0;
return 0;
}
static int
accept_connection (assuan_context_t ctx)
{
assuan_fd_t fd;
struct sockaddr_un clnt_addr;
socklen_t len = sizeof clnt_addr;
fd = SOCKET2HANDLE(accept (HANDLE2SOCKET(ctx->listen_fd),
(struct sockaddr*)&clnt_addr, &len ));
if (fd == ASSUAN_INVALID_FD)
{
ctx->os_errno = errno;
return _assuan_error (ASSUAN_Accept_Failed);
}
if (_assuan_sock_check_nonce (fd, &ctx->listen_nonce))
{
_assuan_close (fd);
ctx->os_errno = EACCES;
return _assuan_error (ASSUAN_Accept_Failed);
}
ctx->connected_fd = fd;
return accept_connection_bottom (ctx);
}
static int
finish_connection (assuan_context_t ctx)
{
if (ctx->inbound.fd != ASSUAN_INVALID_FD)
{
_assuan_close (ctx->inbound.fd);
}
ctx->inbound.fd = ASSUAN_INVALID_FD;
ctx->outbound.fd = ASSUAN_INVALID_FD;
return 0;
}
static void
deinit_socket_server (assuan_context_t ctx)
{
finish_connection (ctx);
}
/* Initialize a server for the socket LISTEN_FD which has already be
put into listen mode */
int
assuan_init_socket_server (assuan_context_t *r_ctx, assuan_fd_t listen_fd)
{
return assuan_init_socket_server_ext (r_ctx, listen_fd, 0);
}
/* Initialize a server using the already accepted socket FD. This
function is deprecated. */
int
assuan_init_connected_socket_server (assuan_context_t *r_ctx, assuan_fd_t fd)
{
return assuan_init_socket_server_ext (r_ctx, fd, 2);
}
/*
Flag bits: 0 - use sendmsg/recvmsg to allow descriptor passing
1 - FD has already been accepted.
*/
int
assuan_init_socket_server_ext (assuan_context_t *r_ctx, assuan_fd_t fd,
unsigned int flags)
{
assuan_context_t ctx;
int rc;
*r_ctx = NULL;
ctx = xtrycalloc (1, sizeof *ctx);
if (!ctx)
return _assuan_error (ASSUAN_Out_Of_Core);
ctx->is_server = 1;
if ((flags & 2))
ctx->pipe_mode = 1; /* We want a second accept to indicate EOF. */
ctx->input_fd = ASSUAN_INVALID_FD;
ctx->output_fd = ASSUAN_INVALID_FD;
ctx->inbound.fd = ASSUAN_INVALID_FD;
ctx->outbound.fd = ASSUAN_INVALID_FD;
if ((flags & 2))
{
ctx->listen_fd = ASSUAN_INVALID_FD;
ctx->connected_fd = fd;
}
else
{
ctx->listen_fd = fd;
ctx->connected_fd = ASSUAN_INVALID_FD;
}
ctx->deinit_handler = (flags & 1)? _assuan_uds_deinit:deinit_socket_server;
ctx->accept_handler = ((flags & 2)
? accept_connection_bottom
: accept_connection);
ctx->finish_handler = finish_connection;
ctx->io = &io;
if ((flags & 1))
_assuan_init_uds_io (ctx);
rc = _assuan_register_std_commands (ctx);
if (rc)
xfree (ctx);
else
*r_ctx = ctx;
return rc;
}
/* Save a copy of NONCE in context CTX. This should be used to
register the server's nonce with an context established by
assuan_init_socket_server. */
void
assuan_set_sock_nonce (assuan_context_t ctx, assuan_sock_nonce_t *nonce)
{
if (ctx && nonce)
ctx->listen_nonce = *nonce;
}

View File

@ -1,470 +0,0 @@
/* assuan-socket.c
* Copyright (C) 2004, 2005 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_W32_SYSTEM
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <wincrypt.h>
#include <io.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#endif
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include "assuan-defs.h"
/* Hacks for Slowaris. */
#ifndef PF_LOCAL
# ifdef PF_UNIX
# define PF_LOCAL PF_UNIX
# else
# define PF_LOCAL AF_UNIX
# endif
#endif
#ifndef AF_LOCAL
# define AF_LOCAL AF_UNIX
#endif
#ifdef HAVE_W32_SYSTEM
#ifndef S_IRGRP
# define S_IRGRP 0
# define S_IWGRP 0
#endif
#endif
#ifdef HAVE_W32_SYSTEM
int
_assuan_sock_wsa2errno (int err)
{
switch (err)
{
case WSAENOTSOCK:
return EINVAL;
case WSAEWOULDBLOCK:
return EAGAIN;
case ERROR_BROKEN_PIPE:
return EPIPE;
case WSANOTINITIALISED:
return ENOSYS;
default:
return EIO;
}
}
/* W32: Fill BUFFER with LENGTH bytes of random. Returns -1 on
failure, 0 on success. Sets errno on failure. */
static int
get_nonce (char *buffer, size_t nbytes)
{
HCRYPTPROV prov;
int ret = -1;
if (!CryptAcquireContext (&prov, NULL, NULL, PROV_RSA_FULL,
(CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) )
errno = ENODEV;
else
{
if (!CryptGenRandom (prov, nbytes, buffer))
errno = ENODEV;
else
ret = 0;
CryptReleaseContext (prov, 0);
}
return ret;
}
/* W32: The buffer for NONCE needs to be at least 16 bytes. Returns 0 on
success and sets errno on failure. */
static int
read_port_and_nonce (const char *fname, unsigned short *port, char *nonce)
{
FILE *fp;
char buffer[50], *p;
size_t nread;
int aval;
fp = fopen (fname, "rb");
if (!fp)
return -1;
nread = fread (buffer, 1, sizeof buffer - 1, fp);
fclose (fp);
if (!nread)
{
errno = ENOFILE;
return -1;
}
buffer[nread] = 0;
aval = atoi (buffer);
if (aval < 1 || aval > 65535)
{
errno = EINVAL;
return -1;
}
*port = (unsigned int)aval;
for (p=buffer; nread && *p != '\n'; p++, nread--)
;
if (*p != '\n' || nread != 17)
{
errno = EINVAL;
return -1;
}
p++; nread--;
memcpy (nonce, p, 16);
return 0;
}
#endif /*HAVE_W32_SYSTEM*/
int
_assuan_close (assuan_fd_t fd)
{
#ifdef _ASSUAN_CUSTOM_IO
return _assuan_custom_close (fd);
#else
#ifdef (HAVE_W32_SYSTEM)
int rc = closesocket (HANDLE2SOCKET(fd));
if (rc)
errno = _assuan_sock_wsa2errno (WSAGetLastError ());
if (rc && WSAGetLastError () == WSAENOTSOCK)
{
rc = CloseHandle (fd);
if (rc)
/* FIXME. */
errno = EIO;
}
return rc;
#else
return close (fd);
#endif
#endif
}
/* Return a new socket. Note that under W32 we consider a socket the
same as an System Handle; all functions using such a handle know
about this dual use and act accordingly. */
assuan_fd_t
_assuan_sock_new (int domain, int type, int proto)
{
#ifdef HAVE_W32_SYSTEM
assuan_fd_t res;
if (domain == AF_UNIX || domain == AF_LOCAL)
domain = AF_INET;
#ifdef _ASSUAN_CUSTOM_IO
return _assuan_custom_socket (domain, type, proto);
#else
res = SOCKET2HANDLE(socket (domain, type, proto));
if (res == ASSUAN_INVALID_FD)
errno = _assuan_sock_wsa2errno (WSAGetLastError ());
return res;
#endif
#else
#ifdef _ASSUAN_CUSTOM_IO
return _gpgme_io_socket (domain, type, proto);
#else
return socket (domain, type, proto);
#endif
#endif
}
int
_assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
{
#ifdef HAVE_W32_SYSTEM
if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
{
struct sockaddr_in myaddr;
struct sockaddr_un *unaddr;
unsigned short port;
char nonce[16];
int ret;
unaddr = (struct sockaddr_un *)addr;
if (read_port_and_nonce (unaddr->sun_path, &port, nonce))
return -1;
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons (port);
myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
/* Set return values. */
unaddr->sun_family = myaddr.sin_family;
unaddr->sun_port = myaddr.sin_port;
unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
#ifdef _ASSUAN_CUSTOM_IO
ret = _assuan_custom_connect (sockfd,
(struct sockaddr *)&myaddr, sizeof myaddr);
#else
ret = connect (HANDLE2SOCKET(sockfd),
(struct sockaddr *)&myaddr, sizeof myaddr);
#endif
if (!ret)
{
/* Send the nonce. */
ret = _assuan_io_write (sockfd, nonce, 16);
if (ret >= 0 && ret != 16)
{
errno = EIO;
ret = -1;
}
}
else
errno = _assuan_sock_wsa2errno (WSAGetLastError ());
return ret;
}
else
{
int res;
res = connect (HANDLE2SOCKET (sockfd), addr, addrlen);
if (res < 0)
errno = _assuan_sock_wsa2errno (WSAGetLastError ());
return res;
}
#else
#ifdef _ASSUAN_CUSTOM_IO
return _assuan_custom_connect (sockfd, addr, addrlen);
#else
return connect (sockfd, addr, addrlen);
#endif
#endif
}
int
_assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
{
#ifdef HAVE_W32_SYSTEM
if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
{
struct sockaddr_in myaddr;
struct sockaddr_un *unaddr;
int filefd;
FILE *fp;
int len = sizeof myaddr;
int rc;
char nonce[16];
if (get_nonce (nonce, 16))
return -1;
unaddr = (struct sockaddr_un *)addr;
myaddr.sin_port = 0;
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
filefd = open (unaddr->sun_path,
(O_WRONLY|O_CREAT|O_EXCL|O_BINARY),
(S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP));
if (filefd == -1)
{
if (errno == EEXIST)
errno = WSAEADDRINUSE;
return -1;
}
fp = fdopen (filefd, "wb");
if (!fp)
{
int save_e = errno;
close (filefd);
errno = save_e;
return -1;
}
rc = bind (HANDLE2SOCKET (sockfd), (struct sockaddr *)&myaddr, len);
if (!rc)
rc = getsockname (HANDLE2SOCKET (sockfd),
(struct sockaddr *)&myaddr, &len);
if (rc)
{
int save_e = errno;
fclose (fp);
remove (unaddr->sun_path);
errno = save_e;
return rc;
}
fprintf (fp, "%d\n", ntohs (myaddr.sin_port));
fwrite (nonce, 16, 1, fp);
fclose (fp);
return 0;
}
else
{
int res = bind (HANDLE2SOCKET(sockfd), addr, addrlen);
if (res < 0)
errno = _assuan_sock_wsa2errno (WSAGetLastError ());
return res;
}
#else
return bind (sockfd, addr, addrlen);
#endif
}
int
_assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,
assuan_sock_nonce_t *nonce)
{
#ifdef HAVE_W32_SYSTEM
if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
{
struct sockaddr_un *unaddr;
unsigned short port;
if (sizeof nonce->nonce != 16)
{
errno = EINVAL;
return -1;
}
nonce->length = 16;
unaddr = (struct sockaddr_un *)addr;
if (read_port_and_nonce (unaddr->sun_path, &port, nonce->nonce))
return -1;
}
else
{
nonce->length = 42; /* Arbitrary valuie to detect unitialized nonce. */
nonce->nonce[0] = 42;
}
#else
(void)addr;
(void)addrlen;
nonce->length = 0;
#endif
return 0;
}
int
_assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce)
{
#ifdef HAVE_W32_SYSTEM
char buffer[16], *p;
size_t nleft;
int n;
if (sizeof nonce->nonce != 16)
{
errno = EINVAL;
return -1;
}
if (nonce->length == 42 && nonce->nonce[0] == 42)
return 0; /* Not a Unix domain socket. */
if (nonce->length != 16)
{
errno = EINVAL;
return -1;
}
p = buffer;
nleft = 16;
while (nleft)
{
n = _assuan_io_read (SOCKET2HANDLE(fd), p, nleft);
if (n < 0 && errno == EINTR)
;
else if (n < 0 && errno == EAGAIN)
Sleep (100);
else if (n < 0)
return -1;
else if (!n)
{
errno = EIO;
return -1;
}
else
{
p += n;
nleft -= n;
}
}
if (memcmp (buffer, nonce->nonce, 16))
{
errno = EACCES;
return -1;
}
#else
(void)fd;
(void)nonce;
#endif
return 0;
}
/* Public API. */
int
assuan_sock_close (assuan_fd_t fd)
{
return _assuan_close (fd);
}
assuan_fd_t
assuan_sock_new (int domain, int type, int proto)
{
return _assuan_sock_new (domain, type, proto);
}
int
assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
{
return _assuan_sock_connect (sockfd, addr, addrlen);
}
int
assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
{
return _assuan_sock_bind (sockfd, addr, addrlen);
}
int
assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,
assuan_sock_nonce_t *nonce)
{
return _assuan_sock_get_nonce (addr, addrlen, nonce);
}
int
assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce)
{
return _assuan_sock_check_nonce (fd, nonce);
}

View File

@ -1,313 +0,0 @@
/* assuan-uds.c - Assuan unix domain socket utilities
* Copyright (C) 2006 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#ifndef HAVE_W32_SYSTEM
#include <sys/socket.h>
#include <sys/un.h>
#else
#include <windows.h>
#endif
#if HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <assert.h>
#include "assuan-defs.h"
#ifdef USE_DESCRIPTOR_PASSING
/* Provide replacement for missing CMSG maccros. We assume that
size_t matches the alignment requirement. */
#define MY_ALIGN(n) ((((n))+ sizeof(size_t)-1) & (size_t)~(sizeof(size_t)-1))
#ifndef CMSG_SPACE
#define CMSG_SPACE(n) (MY_ALIGN(sizeof(struct cmsghdr)) + MY_ALIGN((n)))
#endif
#ifndef CMSG_LEN
#define CMSG_LEN(n) (MY_ALIGN(sizeof(struct cmsghdr)) + (n))
#endif
#ifndef CMSG_FIRSTHDR
#define CMSG_FIRSTHDR(mhdr) \
((size_t)(mhdr)->msg_controllen >= sizeof (struct cmsghdr) \
? (struct cmsghdr*) (mhdr)->msg_control : (struct cmsghdr*)NULL)
#endif
#ifndef CMSG_DATA
#define CMSG_DATA(cmsg) ((unsigned char*)((struct cmsghdr*)(cmsg)+1))
#endif
#endif /*USE_DESCRIPTOR_PASSING*/
/* Read from a unix domain socket using sendmsg.
FIXME: We don't need the buffering. It is a leftover from the time
when we used datagrams. */
static ssize_t
uds_reader (assuan_context_t ctx, void *buf, size_t buflen)
{
#ifndef HAVE_W32_SYSTEM
int len = ctx->uds.buffersize;
if (!ctx->uds.bufferallocated)
{
ctx->uds.buffer = xtrymalloc (2048);
if (!ctx->uds.buffer)
return _assuan_error (ASSUAN_Out_Of_Core);
ctx->uds.bufferallocated = 2048;
}
while (!len) /* No data is buffered. */
{
struct msghdr msg;
struct iovec iovec;
#ifdef USE_DESCRIPTOR_PASSING
union {
struct cmsghdr cm;
char control[CMSG_SPACE(sizeof (int))];
} control_u;
struct cmsghdr *cmptr;
#endif /*USE_DESCRIPTOR_PASSING*/
memset (&msg, 0, sizeof (msg));
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iovec;
msg.msg_iovlen = 1;
iovec.iov_base = ctx->uds.buffer;
iovec.iov_len = ctx->uds.bufferallocated;
#ifdef USE_DESCRIPTOR_PASSING
msg.msg_control = control_u.control;
msg.msg_controllen = sizeof (control_u.control);
#endif
len = _assuan_simple_recvmsg (ctx, &msg);
if (len < 0)
return -1;
if (len == 0)
return 0;
ctx->uds.buffersize = len;
ctx->uds.bufferoffset = 0;
#ifdef USE_DESCRIPTOR_PASSING
cmptr = CMSG_FIRSTHDR (&msg);
if (cmptr && cmptr->cmsg_len == CMSG_LEN (sizeof(int)))
{
if (cmptr->cmsg_level != SOL_SOCKET
|| cmptr->cmsg_type != SCM_RIGHTS)
_assuan_log_printf ("unexpected ancillary data received\n");
else
{
int fd = *((int*)CMSG_DATA (cmptr));
if (ctx->uds.pendingfdscount >= DIM (ctx->uds.pendingfds))
{
_assuan_log_printf ("too many descriptors pending - "
"closing received descriptor %d\n", fd);
_assuan_close (fd);
}
else
ctx->uds.pendingfds[ctx->uds.pendingfdscount++] = fd;
}
}
#endif /*USE_DESCRIPTOR_PASSING*/
}
/* Return some data to the user. */
if (len > buflen) /* We have more than the user requested. */
len = buflen;
memcpy (buf, (char*)ctx->uds.buffer + ctx->uds.bufferoffset, len);
ctx->uds.buffersize -= len;
assert (ctx->uds.buffersize >= 0);
ctx->uds.bufferoffset += len;
assert (ctx->uds.bufferoffset <= ctx->uds.bufferallocated);
return len;
#else /*HAVE_W32_SYSTEM*/
int res = recvfrom (HANDLE2SOCKET(ctx->inbound.fd), buf, buflen, 0, NULL, NULL);
if (res < 0)
errno = _assuan_sock_wsa2errno (WSAGetLastError ());
return res;
#endif /*HAVE_W32_SYSTEM*/
}
/* Write to the domain server. */
static ssize_t
uds_writer (assuan_context_t ctx, const void *buf, size_t buflen)
{
#ifndef HAVE_W32_SYSTEM
struct msghdr msg;
struct iovec iovec;
ssize_t len;
memset (&msg, 0, sizeof (msg));
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iovlen = 1;
msg.msg_iov = &iovec;
iovec.iov_base = (void*)buf;
iovec.iov_len = buflen;
len = _assuan_simple_sendmsg (ctx, &msg);
return len;
#else /*HAVE_W32_SYSTEM*/
int res = sendto (HANDLE2SOCKET(ctx->outbound.fd), buf, buflen, 0,
(struct sockaddr *)&ctx->serveraddr,
sizeof (struct sockaddr_in));
if (res < 0)
errno = _assuan_sock_wsa2errno (WSAGetLastError ());
return res;
#endif /*HAVE_W32_SYSTEM*/
}
static assuan_error_t
uds_sendfd (assuan_context_t ctx, assuan_fd_t fd)
{
#ifdef USE_DESCRIPTOR_PASSING
struct msghdr msg;
struct iovec iovec;
union {
struct cmsghdr cm;
char control[CMSG_SPACE(sizeof (int))];
} control_u;
struct cmsghdr *cmptr;
int len;
char buffer[80];
/* We need to send some real data so that a read won't return 0
which will be taken as an EOF. It also helps with debugging. */
snprintf (buffer, sizeof(buffer)-1, "# descriptor %d is in flight\n", fd);
buffer[sizeof(buffer)-1] = 0;
memset (&msg, 0, sizeof (msg));
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iovlen = 1;
msg.msg_iov = &iovec;
iovec.iov_base = buffer;
iovec.iov_len = strlen (buffer);
msg.msg_control = control_u.control;
msg.msg_controllen = sizeof (control_u.control);
cmptr = CMSG_FIRSTHDR (&msg);
cmptr->cmsg_len = CMSG_LEN(sizeof(int));
cmptr->cmsg_level = SOL_SOCKET;
cmptr->cmsg_type = SCM_RIGHTS;
*((int*)CMSG_DATA (cmptr)) = fd;
len = _assuan_simple_sendmsg (ctx, &msg);
if (len < 0)
{
_assuan_log_printf ("uds_sendfd: %s\n", strerror (errno));
return _assuan_error (ASSUAN_Write_Error);
}
else
return 0;
#else
return _assuan_error (ASSUAN_Not_Implemented);
#endif
}
static assuan_error_t
uds_receivefd (assuan_context_t ctx, assuan_fd_t *fd)
{
#ifdef USE_DESCRIPTOR_PASSING
int i;
if (!ctx->uds.pendingfdscount)
{
_assuan_log_printf ("no pending file descriptors!\n");
return _assuan_error (ASSUAN_General_Error);
}
assert (ctx->uds.pendingfdscount <= DIM(ctx->uds.pendingfds));
*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--;
return 0;
#else
return _assuan_error (ASSUAN_Not_Implemented);
#endif
}
/* Close all pending fds. */
void
_assuan_uds_close_fds (assuan_context_t ctx)
{
int i;
for (i = 0; i < ctx->uds.pendingfdscount; i++)
_assuan_close (ctx->uds.pendingfds[i]);
ctx->uds.pendingfdscount = 0;
}
/* Deinitialize the unix domain socket I/O functions. */
void
_assuan_uds_deinit (assuan_context_t ctx)
{
/* First call the finish_handler which should close descriptors etc. */
ctx->finish_handler (ctx);
if (ctx->uds.buffer)
{
assert (ctx->uds.bufferallocated);
ctx->uds.bufferallocated = 0;
xfree (ctx->uds.buffer);
}
_assuan_uds_close_fds (ctx);
}
/* Helper function to initialize a context for domain I/O. */
void
_assuan_init_uds_io (assuan_context_t ctx)
{
static struct assuan_io io = { uds_reader, uds_writer,
uds_sendfd, uds_receivefd };
ctx->io = &io;
ctx->uds.buffer = 0;
ctx->uds.bufferoffset = 0;
ctx->uds.buffersize = 0;
ctx->uds.bufferallocated = 0;
ctx->uds.pendingfdscount = 0;
}

View File

@ -1,188 +0,0 @@
/* assuan-util.c - Utility functions for Assuan
* Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "assuan-defs.h"
static void *(*alloc_func)(size_t n) = malloc;
static void *(*realloc_func)(void *p, size_t n) = realloc;
static void (*free_func)(void*) = free;
struct assuan_io_hooks _assuan_io_hooks;
void
assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
void *(*new_realloc_func)(void *p, size_t n),
void (*new_free_func)(void*) )
{
alloc_func = new_alloc_func;
realloc_func = new_realloc_func;
free_func = new_free_func;
}
void
assuan_set_io_hooks (assuan_io_hooks_t io_hooks)
{
_assuan_io_hooks.read_hook = NULL;
_assuan_io_hooks.write_hook = NULL;
if (io_hooks)
{
_assuan_io_hooks.read_hook = io_hooks->read_hook;
_assuan_io_hooks.write_hook = io_hooks->write_hook;
}
}
void *
_assuan_malloc (size_t n)
{
return alloc_func (n);
}
void *
_assuan_realloc (void *a, size_t n)
{
return realloc_func (a, n);
}
void *
_assuan_calloc (size_t n, size_t m)
{
void *p;
size_t nbytes;
nbytes = n * m;
if (m && nbytes / m != n)
{
errno = ENOMEM;
return NULL;
}
p = _assuan_malloc (nbytes);
if (p)
memset (p, 0, nbytes);
return p;
}
void
_assuan_free (void *p)
{
if (p)
free_func (p);
}
/* Store the error in the context so that the error sending function
can take out a descriptive text. Inside the assuan code, use the
macro set_error instead of this function. */
int
assuan_set_error (assuan_context_t ctx, int err, const char *text)
{
ctx->err_no = err;
ctx->err_str = text;
return err;
}
void
assuan_set_pointer (assuan_context_t ctx, void *pointer)
{
if (ctx)
ctx->user_pointer = pointer;
}
void *
assuan_get_pointer (assuan_context_t ctx)
{
return ctx? ctx->user_pointer : NULL;
}
void
assuan_begin_confidential (assuan_context_t ctx)
{
if (ctx)
{
ctx->confidential = 1;
}
}
void
assuan_end_confidential (assuan_context_t ctx)
{
if (ctx)
{
ctx->confidential = 0;
}
}
void
assuan_set_io_monitor (assuan_context_t ctx,
unsigned int (*monitor)(assuan_context_t ctx,
int direction,
const char *line,
size_t linelen))
{
if (ctx)
{
ctx->io_monitor = monitor;
}
}
/* For context CTX, set the flag FLAG to VALUE. Values for flags
are usually 1 or 0 but certain flags might allow for other values;
see the description of the type assuan_flag_t for details. */
void
assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value)
{
if (!ctx)
return;
switch (flag)
{
case ASSUAN_NO_WAITPID: ctx->flags.no_waitpid = value; break;
case ASSUAN_CONFIDENTIAL: ctx->confidential = value; break;
}
}
/* Return the VALUE of FLAG in context CTX. */
int
assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag)
{
if (!ctx)
return 0;
switch (flag)
{
case ASSUAN_NO_WAITPID: return ctx->flags.no_waitpid;
case ASSUAN_CONFIDENTIAL: return ctx->confidential;
}
return 0;
}

View File

@ -1,700 +0,0 @@
/* assuan.h - Definitions for the Assuan IPC library
* Copyright (C) 2001, 2002, 2003, 2005, 2007,
* 2008 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ASSUAN_H
#define ASSUAN_H
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#ifndef _ASSUAN_NO_SOCKET_WRAPPER
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#endif
#endif /*!_ASSUAN_NO_SOCKET_WRAPPER*/
/* To use this file with libraries the following macros are useful:
#define _ASSUAN_EXT_SYM_PREFIX _foo_
This prefixes all external symbols with "_foo_".
#define _ASSUAN_ONLY_GPG_ERRORS
If this is defined all old-style Assuan error codes are made
inactive as well as other deprecated stuff.
#define _ASSUAN_NO_SOCKET_WRAPPER
Do not include the definitions for the socket wrapper feature.
The follwing macros are used internally in the implementation of
libassuan:
#define _ASSUAN_NO_PTH
This avoids inclusion of special GNU Pth hacks.
#define _ASSUAN_NO_FIXED_SIGNALS
This disables changing of certain signal handler; i.e. SIGPIPE.
#define _ASSUAN_USE_DOUBLE_FORK
Use a double fork approach when connecting to a server through
a pipe.
*/
/**** Begin GPGME specific modifications. ******/
#define _ASSUAN_EXT_SYM_PREFIX _gpgme_
#define _ASSUAN_NO_PTH
#define _ASSUAN_NO_FIXED_SIGNALS
#define _ASSUAN_USE_DOUBLE_FORK
#ifdef _ASSUAN_IN_GPGME_BUILD_ASSUAN
#include <ath.h>
int _gpgme_io_close (int fd);
int _gpgme_io_read (int fd, void *buffer, size_t count);
int _gpgme_io_write (int fd, const void *buffer, size_t count);
int _gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen);
int _gpgme_io_sendmsg (int sock, const struct msghdr *msg, int flags);
int _gpgme_io_recvmsg (int sock, struct msghdr *msg, int flags);
int _gpgme_io_socket (int domain, int type, int proto);
#define _assuan_funopen _gpgme_funopen
#define close _gpgme_io_close
#define read _gpgme_io_read
#define write _gpgme_io_write
#define waitpid _gpgme_ath_waitpid
#define select _gpgme_ath_select
#define accept _gpgme_ath_accept
#define connect _gpgme_ath_connect
#define sendmsg _gpgme_io_sendmsg
#define recvmsg _gpgme_io_recvmsg
#endif /*_ASSUAN_IN_GPGME_BUILD_ASSUAN*/
#define _ASSUAN_CUSTOM_IO 1
#define _assuan_custom_close _gpgme_io_close
#define _assuan_custom_read _gpgme_io_read
#define _assuan_custom_write _gpgme_io_write
#define _assuan_custom_pipe _gpgme_io_pipe
#define _assuan_custom_socket _gpgme_io_socket
#define _assuan_custom_connect _gpgme_io_connect
/**** End GPGME specific modifications. ******/
#ifdef _ASSUAN_EXT_SYM_PREFIX
#define _ASSUAN_PREFIX1(x,y) x ## y
#define _ASSUAN_PREFIX2(x,y) _ASSUAN_PREFIX1(x,y)
#define _ASSUAN_PREFIX(x) _ASSUAN_PREFIX2(_ASSUAN_EXT_SYM_PREFIX,x)
#define assuan_ _ASSUAN_PREFIX(assuan_)
#define assuan_register_command _ASSUAN_PREFIX(assuan_register_command)
#define assuan_register_post_cmd_notify \
_ASSUAN_PREFIX(assuan_register_post_cmd_notify)
#define assuan_register_bye_notify _ASSUAN_PREFIX(assuan_register_bye_notify)
#define assuan_register_reset_notify \
_ASSUAN_PREFIX(assuan_register_reset_notify)
#define assuan_register_cancel_notify \
_ASSUAN_PREFIX(assuan_register_cancel_notify)
#define assuan_register_input_notify \
_ASSUAN_PREFIX(assuan_register_input_notify)
#define assuan_register_output_notify \
_ASSUAN_PREFIX(assuan_register_output_notify)
#define assuan_register_option_handler \
_ASSUAN_PREFIX(assuan_register_option_handler)
#define assuan_process _ASSUAN_PREFIX(assuan_process)
#define assuan_process_next _ASSUAN_PREFIX(assuan_process_next)
#define assuan_process_done _ASSUAN_PREFIX(assuan_process_done)
#define assuan_get_active_fds _ASSUAN_PREFIX(assuan_get_active_fds)
#define assuan_get_data_fp _ASSUAN_PREFIX(assuan_get_data_fp)
#define assuan_set_okay_line _ASSUAN_PREFIX(assuan_set_okay_line)
#define assuan_write_status _ASSUAN_PREFIX(assuan_write_status)
#define assuan_command_parse_fd _ASSUAN_PREFIX(assuan_command_parse_fd)
#define assuan_set_hello_line _ASSUAN_PREFIX(assuan_set_hello_line)
#define assuan_accept _ASSUAN_PREFIX(assuan_accept)
#define assuan_get_input_fd _ASSUAN_PREFIX(assuan_get_input_fd)
#define assuan_get_output_fd _ASSUAN_PREFIX(assuan_get_output_fd)
#define assuan_close_input_fd _ASSUAN_PREFIX(assuan_close_input_fd)
#define assuan_close_output_fd _ASSUAN_PREFIX(assuan_close_output_fd)
#define assuan_init_pipe_server _ASSUAN_PREFIX(assuan_init_pipe_server)
#define assuan_deinit_server _ASSUAN_PREFIX(assuan_deinit_server)
#define assuan_init_socket_server _ASSUAN_PREFIX(assuan_init_socket_server)
#define assuan_init_connected_socket_server \
_ASSUAN_PREFIX(assuan_init_connected_socket_server)
#define assuan_init_socket_server_ext \
_ASSUAN_PREFIX(assuan_init_socket_server_ext)
#define assuan_pipe_connect _ASSUAN_PREFIX(assuan_pipe_connect)
#define assuan_pipe_connect_ext _ASSUAN_PREFIX(assuan_pipe_connect_ext)
#define assuan_socket_connect _ASSUAN_PREFIX(assuan_socket_connect)
#define assuan_socket_connect_ext _ASSUAN_PREFIX(assuan_socket_connect_ext)
#define assuan_disconnect _ASSUAN_PREFIX(assuan_disconnect)
#define assuan_get_pid _ASSUAN_PREFIX(assuan_get_pid)
#define assuan_get_peercred _ASSUAN_PREFIX(assuan_get_peercred)
#define assuan_transact _ASSUAN_PREFIX(assuan_transact)
#define assuan_inquire _ASSUAN_PREFIX(assuan_inquire)
#define assuan_inquire_ext _ASSUAN_PREFIX(assuan_inquire_ext)
#define assuan_read_line _ASSUAN_PREFIX(assuan_read_line)
#define assuan_pending_line _ASSUAN_PREFIX(assuan_pending_line)
#define assuan_write_line _ASSUAN_PREFIX(assuan_write_line)
#define assuan_send_data _ASSUAN_PREFIX(assuan_send_data)
#define assuan_sendfd _ASSUAN_PREFIX(assuan_sendfd)
#define assuan_receivefd _ASSUAN_PREFIX(assuan_receivefd)
#define assuan_set_malloc_hooks _ASSUAN_PREFIX(assuan_set_malloc_hooks)
#define assuan_set_io_hooks _ASSUAN_PREFIX(assuan_set_io_hooks)
#define assuan_set_log_stream _ASSUAN_PREFIX(assuan_set_log_stream)
#define assuan_set_error _ASSUAN_PREFIX(assuan_set_error)
#define assuan_set_pointer _ASSUAN_PREFIX(assuan_set_pointer)
#define assuan_get_pointer _ASSUAN_PREFIX(assuan_get_pointer)
#define assuan_set_io_monitor _ASSUAN_PREFIX(assuan_set_io_monitor)
#define assuan_begin_confidential _ASSUAN_PREFIX(assuan_begin_confidential)
#define assuan_end_confidential _ASSUAN_PREFIX(assuan_end_confidential)
#define assuan_strerror _ASSUAN_PREFIX(assuan_strerror)
#define assuan_set_assuan_err_source \
_ASSUAN_PREFIX(assuan_set_assuan_err_source)
#define assuan_set_assuan_log_stream \
_ASSUAN_PREFIX(assuan_set_assuan_log_stream)
#define assuan_get_assuan_log_stream \
_ASSUAN_PREFIX(assuan_get_assuan_log_stream)
#define assuan_get_assuan_log_prefix \
_ASSUAN_PREFIX(assuan_get_assuan_log_prefix)
#define assuan_set_flag _ASSUAN_PREFIX(assuan_set_flag)
#define assuan_get_flag _ASSUAN_PREFIX(assuan_get_flag)
#define assuan_pipe_connect2 _ASSUAN_PREFIX(assuan_pipe_connect2)
#define assuan_set_assuan_log_prefix \
_ASSUAN_PREFIX(assuan_set_assuan_log_prefix)
#define assuan_sock_close _ASSUAN_PREFIX(assuan_sock_close)
#define assuan_sock_new _ASSUAN_PREFIX(assuan_sock_new)
#define assuan_sock_connect _ASSUAN_PREFIX(assuan_sock_connect)
#define assuan_sock_bind _ASSUAN_PREFIX(assuan_sock_bind)
#define assuan_sock_get_nonce _ASSUAN_PREFIX(assuan_sock_get_nonce)
#define assuan_sock_check_nonce _ASSUAN_PREFIX(assuan_sock_check_nonce)
/* And now the internal functions, argh... */
#define _assuan_read_line _ASSUAN_PREFIX(_assuan_read_line)
#define _assuan_cookie_write_data _ASSUAN_PREFIX(_assuan_cookie_write_data)
#define _assuan_cookie_write_flush _ASSUAN_PREFIX(_assuan_cookie_write_flush)
#define _assuan_read_from_server _ASSUAN_PREFIX(_assuan_read_from_server)
#define _assuan_domain_init _ASSUAN_PREFIX(_assuan_domain_init)
#define _assuan_register_std_commands \
_ASSUAN_PREFIX(_assuan_register_std_commands)
#define _assuan_simple_read _ASSUAN_PREFIX(_assuan_simple_read)
#define _assuan_simple_write _ASSUAN_PREFIX(_assuan_simple_write)
#define _assuan_io_read _ASSUAN_PREFIX(_assuan_io_read)
#define _assuan_io_write _ASSUAN_PREFIX(_assuan_io_write)
#define _assuan_io_hooks _ASSUAN_PREFIX(_assuan_io_hooks)
#define _assuan_new_context _ASSUAN_PREFIX(_assuan_new_context)
#define _assuan_release_context _ASSUAN_PREFIX(_assuan_release_context)
#define _assuan_malloc _ASSUAN_PREFIX(_assuan_malloc)
#define _assuan_realloc _ASSUAN_PREFIX(_assuan_realloc)
#define _assuan_calloc _ASSUAN_PREFIX(_assuan_calloc)
#define _assuan_free _ASSUAN_PREFIX(_assuan_free)
#define _assuan_log_print_buffer _ASSUAN_PREFIX(_assuan_log_print_buffer)
#define _assuan_log_sanitized_string \
_ASSUAN_PREFIX(_assuan_log_sanitized_string)
#define _assuan_log_printf _ASSUAN_PREFIX(_assuan_log_printf)
#define _assuan_set_default_log_stream \
_ASSUAN_PREFIX(_assuan_set_default_log_stream)
#define _assuan_w32_strerror _ASSUAN_PREFIX(_assuan_w32_strerror)
#define _assuan_gpg_strerror_r _ASSUAN_PREFIX(_assuan_gpg_strerror_r)
#define _assuan_gpg_strsource _ASSUAN_PREFIX(_assuan_gpg_strsource)
#define _assuan_write_line _ASSUAN_PREFIX(_assuan_write_line)
#define _assuan_error _ASSUAN_PREFIX(_assuan_error)
#define _assuan_error_is_eagain _ASSUAN_PREFIX(_assuan_error_is_eagain)
#define _assuan_init_uds_io _ASSUAN_PREFIX(_assuan_init_uds_io)
#define _assuan_uds_close_fds _ASSUAN_PREFIX(_assuan_uds_close_fds)
#define _assuan_uds_deinit _ASSUAN_PREFIX(_assuan_uds_deinit)
#define _assuan_simple_recvmsg _ASSUAN_PREFIX(_assuan_simple_recvmsg)
#define _assuan_simple_sendmsg _ASSUAN_PREFIX(_assuan_simple_sendmsg)
#define _assuan_waitpid _ASSUAN_PREFIX(_assuan_waitpid)
#define _assuan_sock_wsa2errno _ASSUAN_PREFIX(_assuan_sock_wsa2errno)
#define _assuan_sock_close _ASSUAN_PREFIX(_assuan_sock_close)
#define _assuan_sock_new _ASSUAN_PREFIX(_assuan_sock_new)
#define _assuan_sock_connect _ASSUAN_PREFIX(_assuan_sock_connect)
#define _assuan_sock_bind _ASSUAN_PREFIX(_assuan_sock_bind)
#define _assuan_sock_get_nonce _ASSUAN_PREFIX(_assuan_sock_get_nonce)
#define _assuan_sock_check_nonce _ASSUAN_PREFIX(_assuan_sock_check_nonce)
#define _assuan_close _ASSUAN_PREFIX(_assuan_close)
#define _assuan_usleep _ASSUAN_PREFIX(_assuan_usleep)
#endif /*_ASSUAN_EXT_SYM_PREFIX*/
#ifdef __cplusplus
extern "C"
{
#if 0
}
#endif
#endif
/* Check for compiler features. */
#if __GNUC__
#define _ASSUAN_GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
#if _ASSUAN_GCC_VERSION > 30100
#define _ASSUAN_DEPRECATED __attribute__ ((__deprecated__))
#endif
#endif
#ifndef _ASSUAN_DEPRECATED
#define _ASSUAN_DEPRECATED
#endif
/* Assuan error codes. These are only used by old applications or
those applications which won't make use of libgpg-error. */
#ifndef _ASSUAN_ONLY_GPG_ERRORS
#ifndef _ASSUAN_IN_LIBASSUAN
#define ASSUAN_No_Error 0
#endif
#define ASSUAN_General_Error 1
#define ASSUAN_Out_Of_Core 2
#define ASSUAN_Invalid_Value 3
#ifndef _ASSUAN_IN_LIBASSUAN
#define ASSUAN_Timeout 4
#endif
#define ASSUAN_Read_Error 5
#define ASSUAN_Write_Error 6
#define ASSUAN_Problem_Starting_Server 7
#define ASSUAN_Not_A_Server 8
#ifndef _ASSUAN_IN_LIBASSUAN
#define ASSUAN_Not_A_Client 9
#endif
#define ASSUAN_Nested_Commands 10
#define ASSUAN_Invalid_Response 11
#define ASSUAN_No_Data_Callback 12
#define ASSUAN_No_Inquire_Callback 13
#define ASSUAN_Connect_Failed 14
#define ASSUAN_Accept_Failed 15
/* Error codes above 99 are meant as status codes */
#define ASSUAN_Not_Implemented 100
#define ASSUAN_Server_Fault 101
#ifndef _ASSUAN_IN_LIBASSUAN
#define ASSUAN_Invalid_Command 102
#endif
#define ASSUAN_Unknown_Command 103
#define ASSUAN_Syntax_Error 104
#ifndef _ASSUAN_IN_LIBASSUAN
#define ASSUAN_Parameter_Error 105
#endif
#define ASSUAN_Parameter_Conflict 106
#define ASSUAN_Line_Too_Long 107
#define ASSUAN_Line_Not_Terminated 108
#ifndef _ASSUAN_IN_LIBASSUAN
#define ASSUAN_No_Input 109
#define ASSUAN_No_Output 110
#endif
#define ASSUAN_Canceled 111
#ifndef _ASSUAN_IN_LIBASSUAN
#define ASSUAN_Unsupported_Algorithm 112
#define ASSUAN_Server_Resource_Problem 113
#define ASSUAN_Server_IO_Error 114
#define ASSUAN_Server_Bug 115
#define ASSUAN_No_Data_Available 116
#define ASSUAN_Invalid_Data 117
#endif
#define ASSUAN_Unexpected_Command 118
#define ASSUAN_Too_Much_Data 119
#ifndef _ASSUAN_IN_LIBASSUAN
#define ASSUAN_Inquire_Unknown 120
#define ASSUAN_Inquire_Error 121
#define ASSUAN_Invalid_Option 122
#define ASSUAN_Invalid_Index 123
#define ASSUAN_Unexpected_Status 124
#define ASSUAN_Unexpected_Data 125
#define ASSUAN_Invalid_Status 126
#define ASSUAN_Locale_Problem 127
#endif
#define ASSUAN_Not_Confirmed 128
/* Warning: Don't use the Error codes, below they are deprecated. */
#ifndef _ASSUAN_IN_LIBASSUAN
#define ASSUAN_Bad_Certificate 201
#define ASSUAN_Bad_Certificate_Chain 202
#define ASSUAN_Missing_Certificate 203
#define ASSUAN_Bad_Signature 204
#define ASSUAN_No_Agent 205
#define ASSUAN_Agent_Error 206
#define ASSUAN_No_Public_Key 207
#define ASSUAN_No_Secret_Key 208
#define ASSUAN_Invalid_Name 209
#define ASSUAN_Cert_Revoked 301
#define ASSUAN_No_CRL_For_Cert 302
#define ASSUAN_CRL_Too_Old 303
#define ASSUAN_Not_Trusted 304
#define ASSUAN_Card_Error 401
#define ASSUAN_Invalid_Card 402
#define ASSUAN_No_PKCS15_App 403
#define ASSUAN_Card_Not_Present 404
#define ASSUAN_Invalid_Id 405
/* Error codes in the range 1000 to 9999 may be used by applications
at their own discretion. */
#define ASSUAN_USER_ERROR_FIRST 1000
#define ASSUAN_USER_ERROR_LAST 9999
#endif
typedef int assuan_error_t;
typedef assuan_error_t AssuanError _ASSUAN_DEPRECATED;
/* This is a list of pre-registered ASSUAN commands */
/* Note, these command IDs are now deprectated and solely exists for
compatibility reasons. */
typedef enum
{
ASSUAN_CMD_NOP = 0,
ASSUAN_CMD_CANCEL, /* cancel the current request */
ASSUAN_CMD_BYE,
ASSUAN_CMD_AUTH,
ASSUAN_CMD_RESET,
ASSUAN_CMD_OPTION,
ASSUAN_CMD_DATA,
ASSUAN_CMD_END,
ASSUAN_CMD_INPUT,
ASSUAN_CMD_OUTPUT,
ASSUAN_CMD_USER = 256 /* Other commands should be used with this offset*/
} AssuanCommand;
#else /*!_ASSUAN_ONLY_GPG_ERRORS*/
/* Choose a type compatible with gpg_error_t. */
typedef unsigned int assuan_error_t;
#endif /*!_ASSUAN_ONLY_GPG_ERRORS*/
/* Definitions of flags for assuan_set_flag(). */
typedef enum
{
/* When using a pipe server, by default Assuan will wait for the
forked process to die in assuan_disconnect. In certain cases
this is not desirable. By setting this flag, the waitpid will
be skipped and the caller is responsible to cleanup a forked
process. */
ASSUAN_NO_WAITPID = 1,
/* This flag indicates whether Assuan logging is in confidential
mode. Use assuan_{begin,end}_condidential to change the
mode. */
ASSUAN_CONFIDENTIAL = 2
}
assuan_flag_t;
#define ASSUAN_LINELENGTH 1002 /* 1000 + [CR,]LF */
struct assuan_context_s;
typedef struct assuan_context_s *assuan_context_t;
#ifndef _ASSUAN_ONLY_GPG_ERRORS
typedef struct assuan_context_s *ASSUAN_CONTEXT _ASSUAN_DEPRECATED;
#endif /*_ASSUAN_ONLY_GPG_ERRORS*/
/* Because we use system handles and not libc low level file
descriptors on W32, we need to declare them as HANDLE (which
actually is a plain pointer). This is required to eventually
support 64 bit Windows systems. */
#ifdef _WIN32
typedef void *assuan_fd_t;
#define ASSUAN_INVALID_FD ((void*)(-1))
#define ASSUAN_INT2FD(s) ((void *)(s))
#define ASSUAN_FD2INT(h) ((unsigned int)(h))
#else
typedef int assuan_fd_t;
#define ASSUAN_INVALID_FD (-1)
#define ASSUAN_INT2FD(s) ((s))
#define ASSUAN_FD2INT(h) ((h))
#endif
/* Assuan features an emulation of Unix domain sockets based on a
local TCP connections. To implement access permissions based on
file permissions a nonce is used which is expected by th server as
the first bytes received. This structure is used by the server to
save the nonce created initially by bind. On POSIX systems this is
a dummy operation. */
struct assuan_sock_nonce_s
{
size_t length;
#ifdef _WIN32
char nonce[16];
#endif
};
typedef struct assuan_sock_nonce_s assuan_sock_nonce_t;
/* Define the Unix domain socket structure for Windows. */
#if defined(_WIN32) && !defined(_ASSUAN_NO_SOCKET_WRAPPER)
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
#endif
#define EADDRINUSE WSAEADDRINUSE
struct sockaddr_un
{
short sun_family;
unsigned short sun_port;
struct in_addr sun_addr;
char sun_path[108-2-4];
};
#endif
/* Definition of hook functions used to conditionally replace the
default I/O functions. */
struct assuan_io_hooks
{
int (*read_hook)(assuan_context_t, assuan_fd_t, void *, size_t, ssize_t *);
int (*write_hook)(assuan_context_t, assuan_fd_t fd,
const void *, size_t, ssize_t *);
};
typedef struct assuan_io_hooks *assuan_io_hooks_t;
/*-- assuan-handler.c --*/
int assuan_register_command (assuan_context_t ctx,
const char *cmd_string,
int (*handler)(assuan_context_t, char *));
int assuan_register_post_cmd_notify (assuan_context_t ctx,
void (*fnc)(assuan_context_t, int));
int assuan_register_bye_notify (assuan_context_t ctx,
void (*fnc)(assuan_context_t));
int assuan_register_reset_notify (assuan_context_t ctx,
void (*fnc)(assuan_context_t));
int assuan_register_cancel_notify (assuan_context_t ctx,
void (*fnc)(assuan_context_t));
int assuan_register_input_notify (assuan_context_t ctx,
void (*fnc)(assuan_context_t, const char *));
int assuan_register_output_notify (assuan_context_t ctx,
void (*fnc)(assuan_context_t, const char *));
int assuan_register_option_handler (assuan_context_t ctx,
int (*fnc)(assuan_context_t,
const char*, const char*));
int assuan_process (assuan_context_t ctx);
int assuan_process_next (assuan_context_t ctx);
int assuan_process_done (assuan_context_t ctx, int rc);
int assuan_get_active_fds (assuan_context_t ctx, int what,
assuan_fd_t *fdarray, int fdarraysize);
FILE *assuan_get_data_fp (assuan_context_t ctx);
assuan_error_t assuan_set_okay_line (assuan_context_t ctx, const char *line);
assuan_error_t assuan_write_status (assuan_context_t ctx,
const char *keyword, const char *text);
/* Negotiate a file descriptor. If LINE contains "FD=N", returns N
assuming a local file descriptor. If LINE contains "FD" reads a
file descriptor via CTX and stores it in *RDF (the CTX must be
capable of passing file descriptors). Under W32 the returned FD is
a libc-type one. */
assuan_error_t assuan_command_parse_fd (assuan_context_t ctx, char *line,
assuan_fd_t *rfd);
/*-- assuan-listen.c --*/
assuan_error_t assuan_set_hello_line (assuan_context_t ctx, const char *line);
assuan_error_t assuan_accept (assuan_context_t ctx);
assuan_fd_t assuan_get_input_fd (assuan_context_t ctx);
assuan_fd_t assuan_get_output_fd (assuan_context_t ctx);
assuan_error_t assuan_close_input_fd (assuan_context_t ctx);
assuan_error_t assuan_close_output_fd (assuan_context_t ctx);
/*-- assuan-pipe-server.c --*/
int assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2]);
void assuan_deinit_server (assuan_context_t ctx);
/*-- assuan-socket-server.c --*/
int assuan_init_socket_server (assuan_context_t *r_ctx, assuan_fd_t listen_fd);
int assuan_init_connected_socket_server (assuan_context_t *r_ctx,
assuan_fd_t fd) _ASSUAN_DEPRECATED;
int assuan_init_socket_server_ext (assuan_context_t *r_ctx, assuan_fd_t fd,
unsigned int flags);
void assuan_set_sock_nonce (assuan_context_t ctx, assuan_sock_nonce_t *nonce);
/*-- assuan-pipe-connect.c --*/
assuan_error_t assuan_pipe_connect (assuan_context_t *ctx,
const char *name,
const char *const argv[],
int *fd_child_list);
assuan_error_t assuan_pipe_connect2 (assuan_context_t *ctx,
const char *name,
const char *const argv[],
int *fd_child_list,
void (*atfork) (void*, int),
void *atforkvalue) _ASSUAN_DEPRECATED;
assuan_error_t assuan_pipe_connect_ext (assuan_context_t *ctx,
const char *name,
const char *const argv[],
int *fd_child_list,
void (*atfork) (void *, int),
void *atforkvalue,
unsigned int flags);
/*-- assuan-socket-connect.c --*/
assuan_error_t assuan_socket_connect (assuan_context_t *ctx,
const char *name,
pid_t server_pid);
assuan_error_t assuan_socket_connect_ext (assuan_context_t *ctx,
const char *name,
pid_t server_pid,
unsigned int flags);
/*-- assuan-connect.c --*/
void assuan_disconnect (assuan_context_t ctx);
pid_t assuan_get_pid (assuan_context_t ctx);
#ifndef _WIN32
assuan_error_t assuan_get_peercred (assuan_context_t ctx,
pid_t *pid, uid_t *uid, gid_t *gid);
#endif
/*-- assuan-client.c --*/
assuan_error_t
assuan_transact (assuan_context_t ctx,
const char *command,
assuan_error_t (*data_cb)(void *, const void *, size_t),
void *data_cb_arg,
assuan_error_t (*inquire_cb)(void*, const char *),
void *inquire_cb_arg,
assuan_error_t (*status_cb)(void*, const char *),
void *status_cb_arg);
/*-- assuan-inquire.c --*/
assuan_error_t assuan_inquire (assuan_context_t ctx, const char *keyword,
unsigned char **r_buffer, size_t *r_length,
size_t maxlen);
assuan_error_t assuan_inquire_ext (assuan_context_t ctx, const char *keyword,
size_t maxlen,
int (*cb) (void *cb_data, int rc,
unsigned char *buf,
size_t buf_len),
void *cb_data);
/*-- assuan-buffer.c --*/
assuan_error_t assuan_read_line (assuan_context_t ctx,
char **line, size_t *linelen);
int assuan_pending_line (assuan_context_t ctx);
assuan_error_t assuan_write_line (assuan_context_t ctx, const char *line );
assuan_error_t assuan_send_data (assuan_context_t ctx,
const void *buffer, size_t length);
/* The file descriptor must be pending before assuan_receivefd is
called. This means that assuan_sendfd should be called *before* the
trigger is sent (normally via assuan_write_line ("INPUT FD")). */
assuan_error_t assuan_sendfd (assuan_context_t ctx, assuan_fd_t fd);
assuan_error_t assuan_receivefd (assuan_context_t ctx, assuan_fd_t *fd);
/*-- assuan-util.c --*/
void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
void *(*new_realloc_func)(void *p, size_t n),
void (*new_free_func)(void*) );
void assuan_set_io_hooks (assuan_io_hooks_t io_hooks);
void assuan_set_log_stream (assuan_context_t ctx, FILE *fp);
int assuan_set_error (assuan_context_t ctx, int err, const char *text);
void assuan_set_pointer (assuan_context_t ctx, void *pointer);
void *assuan_get_pointer (assuan_context_t ctx);
void assuan_begin_confidential (assuan_context_t ctx);
void assuan_end_confidential (assuan_context_t ctx);
void assuan_set_io_monitor (assuan_context_t ctx,
unsigned int (*monitor)(assuan_context_t ctx,
int direction,
const char *line,
size_t linelen));
/* For context CTX, set the flag FLAG to VALUE. Values for flags
are usually 1 or 0 but certain flags might allow for other values;
see the description of the type assuan_flag_t for details. */
void assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value);
/* Return the VALUE of FLAG in context CTX. */
int assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag);
/*-- assuan-errors.c --*/
#ifndef _ASSUAN_ONLY_GPG_ERRORS
/* Return a string describing the assuan error. The use of this
function is deprecated; it is better to call
assuan_set_assuan_err_source once and then make use libgpg-error. */
const char *assuan_strerror (assuan_error_t err);
#endif /*_ASSUAN_ONLY_GPG_ERRORS*/
/* Enable gpg-error style error codes. ERRSOURCE is one of gpg-error
sources. Note, that this function is not thread-safe and should be
used right at startup. Switching back to the old style mode is not
supported. */
void assuan_set_assuan_err_source (int errsource);
/*-- assuan-logging.c --*/
/* Set the stream to which assuan should log message not associated
with a context. By default, this is stderr. The default value
will be changed when the first log stream is associated with a
context. Note, that this function is not thread-safe and should
in general be used right at startup. */
extern void assuan_set_assuan_log_stream (FILE *fp);
/* Return the stream which is currently being using for global logging. */
extern FILE *assuan_get_assuan_log_stream (void);
/* Set the prefix to be used at the start of a line emitted by assuan
on the log stream. The default is the empty string. Note, that
this function is not thread-safe and should in general be used
right at startup. */
void assuan_set_assuan_log_prefix (const char *text);
/* Return a prefix to be used at the start of a line emitted by assuan
on the log stream. The default implementation returns the empty
string, i.e. "" */
const char *assuan_get_assuan_log_prefix (void);
/*-- assuan-socket.c --*/
/* These are socket wrapper functions to support an emulation of Unix
domain sockets on Windows W32. */
int assuan_sock_close (assuan_fd_t fd);
assuan_fd_t assuan_sock_new (int domain, int type, int proto);
int assuan_sock_connect (assuan_fd_t sockfd,
struct sockaddr *addr, int addrlen);
int assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen);
int assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,
assuan_sock_nonce_t *nonce);
int assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce);
#ifdef __cplusplus
}
#endif
#endif /* ASSUAN_H */

View File

@ -1,257 +0,0 @@
#!/bin/sh
# mkerrors - Extract error strings from assuan.h
# and create C source for assuan_strerror
# Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
#
# This file is part of Assuan.
#
# Assuan is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of
# the License, or (at your option) any later version.
#
# Assuan is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, see <http://www.gnu.org/licenses/>.
cat <<EOF
/* Generated automatically by mkerrors */
/* Do not edit! See mkerrors for copyright notice. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#undef _ASSUAN_IN_LIBASSUAN /* undef to get all error codes. */
#include "assuan.h"
#include "assuan-defs.h"
/* If true the modern gpg-error style error codes are used in the
API. */
static unsigned int err_source;
/* Enable gpg-error style error codes. ERRSOURCE is one of gpg-error
sources. Note, that this function is not thread-safe and should be
used right at startup. Switching back to the old style mode is not
supported. */
void
assuan_set_assuan_err_source (int errsource)
{
errsource &= 0xff;
err_source = errsource? errsource : 31 /*GPG_ERR_SOURCE_ANY*/;
}
/* Helper to map old style Assuan error codes to gpg-error codes.
This is used internally to keep an compatible ABI. */
assuan_error_t
_assuan_error (int oldcode)
{
unsigned int n;
if (!err_source)
{
if (oldcode == -1)
return -1;
else
return (oldcode & 0x00ffffff); /* Make sure that the gpg-error
source part is cleared. */
}
switch (oldcode)
{
case ASSUAN_General_Error: n = 257; break;
case ASSUAN_Accept_Failed: n = 258; break;
case ASSUAN_Connect_Failed: n = 259; break;
case ASSUAN_Invalid_Response: n = 260; break;
case ASSUAN_Invalid_Value: n = 261; break;
case ASSUAN_Line_Not_Terminated: n = 262; break;
case ASSUAN_Line_Too_Long: n = 263; break;
case ASSUAN_Nested_Commands: n = 264; break;
case ASSUAN_No_Data_Callback: n = 265; break;
case ASSUAN_No_Inquire_Callback: n = 266; break;
case ASSUAN_Not_A_Server: n = 267; break;
case ASSUAN_Not_Implemented: n = 69; break;
case ASSUAN_Parameter_Conflict: n = 280; break;
case ASSUAN_Problem_Starting_Server: n = 269; break;
case ASSUAN_Server_Fault: n = 80; break;
case ASSUAN_Syntax_Error: n = 276; break;
case ASSUAN_Too_Much_Data: n = 273; break;
case ASSUAN_Unexpected_Command: n = 274; break;
case ASSUAN_Unknown_Command: n = 275; break;
case ASSUAN_Canceled: n = 277; break;
case ASSUAN_No_Secret_Key: n = 17; break;
case ASSUAN_Not_Confirmed: n = 114; break;
case ASSUAN_Read_Error:
switch (errno)
{
case 0: n = 16381; /*GPG_ERR_MISSING_ERRNO*/ break;
case EAGAIN:
n = (6 | (1 << 15));
break;
default: n = 270; /*GPG_ERR_ASS_READ_ERROR*/ break;
}
break;
case ASSUAN_Write_Error:
switch (errno)
{
case 0: n = 16381; /*GPG_ERR_MISSING_ERRNO*/ break;
case EAGAIN:
n = (6 | (1 << 15));
break;
default: n = 271; /*GPG_ERR_ASS_WRITE_ERROR*/ break;
}
break;
case ASSUAN_Out_Of_Core:
switch (errno)
{
case 0: /* Should not happen but a user might have provided
an incomplete implemented malloc function. Give
him a chance to correct this fault but make sure
an error is indeed returned. */
n = 16381; /*GPG_ERR_MISSING_ERRNO*/
break;
case ENOMEM:
n = (86 | (1 << 15));
break;
default:
n = 16382; /*GPG_ERR_UNKNOWN_ERRNO*/
break;
}
break;
case -1: n = 16383 /*GPG_ERR_EOF*/; break;
default:
n = 257;
break;
}
return ((err_source << 24) | (n & 0x00ffffff));
}
/* A small helper function to treat EAGAIN transparently to the
caller. */
int
_assuan_error_is_eagain (assuan_error_t err)
{
if ((!err_source && err == ASSUAN_Read_Error && errno == EAGAIN)
|| (err_source && (err & ((1 << 24) - 1)) == (6 | (1 << 15))))
{
/* Avoid spinning by sleeping for one tenth of a second. */
_assuan_usleep (100000);
return 1;
}
else
return 0;
}
/**
* assuan_strerror:
* @err: Error code
*
* This function returns a textual representaion of the given
* errorcode. If this is an unknown value, a string with the value
* is returned (Beware: it is hold in a static buffer).
*
* Return value: String with the error description.
**/
const char *
assuan_strerror (assuan_error_t err)
{
const char *s;
static char buf[50];
switch (err)
{
EOF
awk '
/ASSUAN_No_Error/ { okay=1 }
!okay {next}
/^#define[ ]+ASSUAN_[A-Za-z_]*/ { print_code($2) }
/ASSUAN_USER_ERROR_LAST/ { exit 0 }
function print_code( s )
{
printf " case %s: s=\"", s ;
gsub(/_/, " ", s );
printf "%s\"; break;\n", tolower(substr(s,8));
}
'
cat <<EOF
case -1: s = "EOF (-1)"; break;
default:
{
unsigned int source, code, n;
source = ((err >> 24) & 0xff);
code = (err & 0x00ffffff);
if (source)
{
/* Assume this is an libgpg-error and try to map the codes
back. */
switch (code)
{
case 257: n = ASSUAN_General_Error ; break;
case 258: n = ASSUAN_Accept_Failed ; break;
case 259: n = ASSUAN_Connect_Failed ; break;
case 260: n = ASSUAN_Invalid_Response ; break;
case 261: n = ASSUAN_Invalid_Value ; break;
case 262: n = ASSUAN_Line_Not_Terminated ; break;
case 263: n = ASSUAN_Line_Too_Long ; break;
case 264: n = ASSUAN_Nested_Commands ; break;
case 265: n = ASSUAN_No_Data_Callback ; break;
case 266: n = ASSUAN_No_Inquire_Callback ; break;
case 267: n = ASSUAN_Not_A_Server ; break;
case 69: n = ASSUAN_Not_Implemented ; break;
case 280: n = ASSUAN_Parameter_Conflict ; break;
case 269: n = ASSUAN_Problem_Starting_Server; break;
case 270: n = ASSUAN_Read_Error ; break;
case 271: n = ASSUAN_Write_Error ; break;
case 80: n = ASSUAN_Server_Fault ; break;
case 276: n = ASSUAN_Syntax_Error ; break;
case 273: n = ASSUAN_Too_Much_Data ; break;
case 274: n = ASSUAN_Unexpected_Command ; break;
case 275: n = ASSUAN_Unknown_Command ; break;
case 277: n = ASSUAN_Canceled ; break;
case 114: n = ASSUAN_Not_Confirmed ; break;
case ((1<<15)|86): n = ASSUAN_Out_Of_Core ; break;
default: n = 0; break;
}
if (n)
s = assuan_strerror (n);
else
{
sprintf (buf, "ec=%u.%u", source, code );
s=buf;
}
}
else
{
sprintf (buf, "ec=%d", err );
s=buf;
}
}
break;
}
return s;
}
EOF

View File

@ -188,8 +188,10 @@ AM_CONDITIONAL(HAVE_PTH, test "$have_pth" = "yes")
AM_CONDITIONAL(HAVE_PTHREAD, test "$have_pthread" = "yes")
# Checks for header files.
AC_CHECK_HEADERS(sys/select.h)
AC_CHECK_HEADERS([sys/uio.h])
# Type checks.
@ -219,13 +221,6 @@ if test "$GCC" = yes; then
fi
fi
# Network library fun.
AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, gethostbyname,
[NETLIBS="-lnsl $NETLIBS"]))
AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt,
[NETLIBS="-lsocket $NETLIBS"]))
AC_SUBST(NETLIBS)
# Checks for library functions.
AC_FUNC_FSEEKO
@ -277,7 +272,15 @@ AM_PATH_GPG_ERROR(1.4,, AC_MSG_ERROR([libgpg-error was not found]))
AC_DEFINE(GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_GPGME,
[The default error source for GPGME.])
# And for libassuan.
NEED_LIBASSUAN_VERSION=1.1.0
have_libassuan=no
AM_PATH_LIBASSUAN("$NEED_LIBASSUAN_VERSION",
have_libassuan=yes, have_libassuan=no)
AM_CONDITIONAL(HAVE_ASSUAN, test "$have_libassuan" = "yes")
if test "$have_libassuan" = "yes"; then
AC_DEFINE(ENABLE_ASSUAN,1,[Whether Assuan support is enabled])
fi
# Checks for system services
NEED_GPG_VERSION_DEFAULT=1.3.0
@ -510,6 +513,12 @@ AC_ARG_ENABLE(gpgsm-test,
run_gpgsm_test=$enableval)
AM_CONDITIONAL(RUN_GPGSM_TESTS, test "$run_gpgsm_test" = "yes")
# Require libassuan if GPGSM is here.
require_libassuan=no
if test "$GPGSM" != "no"; then
require_libassuan=yes
fi
NO_OVERRIDE=no
AC_ARG_WITH(gpgconf,
@ -614,13 +623,6 @@ if test "$GPGCONF" != "no"; then
fi
# FIXME: Only build if supported.
AM_CONDITIONAL(BUILD_ASSUAN, test "$GPGSM" != "no")
if test "$GPGSM" != "no"; then
AC_DEFINE(HAVE_ASSUAN_H, 1,
[Defined if we are building with assuan support.])
fi
# Check for funopen
AC_CHECK_FUNCS(funopen)
if test $ac_cv_func_funopen != yes; then
@ -636,18 +638,12 @@ if test $ac_cv_func_funopen != yes; then
fi
fi
# More assuan replacement functions.
AC_REPLACE_FUNCS(isascii)
AC_REPLACE_FUNCS(putc_unlocked)
AC_REPLACE_FUNCS(memrchr)
# Replacement functions.
AC_REPLACE_FUNCS(stpcpy)
# Check for unistd.h for setenv replacement function.
AC_CHECK_HEADERS(unistd.h)
AC_REPLACE_FUNCS(setenv)
# More assuan checks.
AC_CHECK_HEADERS([sys/uio.h])
# Assuan check for descriptor passing.
AC_CHECK_MEMBER(struct cmsghdr.cmsg_len,
[supports_descriptor_passing=yes],
@ -684,27 +680,6 @@ fi
AM_CONDITIONAL(USE_DESCRIPTOR_PASSING, test "$use_descriptor_passing" = "yes")
# Assuan check for the getsockopt SO_PEERCRED
AC_MSG_CHECKING(for SO_PEERCRED)
AC_CACHE_VAL(assuan_cv_sys_so_peercred,
[AC_TRY_COMPILE([#include <sys/socket.h>],
[struct ucred cr;
int cl = sizeof cr;
getsockopt (1, SOL_SOCKET, SO_PEERCRED, &cr, &cl);],
assuan_cv_sys_so_peercred=yes,
assuan_cv_sys_so_peercred=no)
])
AC_MSG_RESULT($assuan_cv_sys_so_peercred)
if test $assuan_cv_sys_so_peercred = yes; then
AC_DEFINE(HAVE_SO_PEERCRED, 1,
[Defined if SO_PEERCRED is supported (Linux specific)])
fi
if test "$have_w32_system" = yes; then
NETLIBS="-lws2_32 $NETLIBS"
fi
# End of assuan checks.
AM_CONDITIONAL(BUILD_COMPLUS, test "$component_system" = "COM+")
@ -753,6 +728,28 @@ LTLIBOBJS=`echo "$LIB@&t@OBJS" |
sed 's,\.[[^.]]* ,.lo ,g;s,\.[[^.]]*$,.lo,'`
AC_SUBST(LTLIBOBJS)
# Last check.
die=no
if test "$require_libassuan" = "no"; then
die=yes
AC_MSG_NOTICE([[
***
*** You need libassuan to build this program with GPGSM support.
*** This library is for example available at
*** ftp://ftp.gnupg.org/pub/gcrypt/alpha/libassuan/
*** (at least version $NEED_LIBASSUAN_VERSION is required).
***]])
fi
if test "$die" = "yes"; then
AC_MSG_ERROR([[
***
*** Required libraries not found. Please consult the above messages
*** and install them before running configure again.
***]])
fi
#
# Create config files
@ -780,6 +777,8 @@ echo "
GpgConf path: $GPGCONF
GpgConf version: $GPGCONF_VERSION, min. $NEED_GPGCONF_VERSION
Assuan version: $LIBASSUAN_VERSION
GPGME Pthread: $have_pthread
GPGME Pth: $have_pth
"

79
m4/libassuan.m4 Normal file
View File

@ -0,0 +1,79 @@
dnl Autoconf macros for libassuan
dnl Copyright (C) 2002, 2003 Free Software Foundation, Inc.
dnl
dnl This file is free software; as a special exception the author gives
dnl unlimited permission to copy and/or distribute it, with or without
dnl modifications, as long as this notice is preserved.
dnl
dnl This file is distributed in the hope that it will be useful, but
dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
dnl AM_PATH_LIBASSUAN([MINIMUM-VERSION,
dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
dnl Test for libassuan and define LIBASSUAN_CFLAGS and LIBASSUAN_LIBS
dnl
AC_DEFUN([AM_PATH_LIBASSUAN],
[ AC_ARG_WITH(libassuan-prefix,
AC_HELP_STRING([--with-libassuan-prefix=PFX],
[prefix where LIBASSUAN is installed (optional)]),
libassuan_config_prefix="$withval", libassuan_config_prefix="")
if test x$libassuan_config_prefix != x ; then
libassuan_config_args="$libassuan_config_args --prefix=$libassuan_config_prefix"
if test x${LIBASSUAN_CONFIG+set} != xset ; then
LIBASSUAN_CONFIG=$libassuan_config_prefix/bin/libassuan-config
fi
fi
AC_PATH_PROG(LIBASSUAN_CONFIG, libassuan-config, no)
min_libassuan_version=ifelse([$1], ,0.0.1,$1)
AC_MSG_CHECKING(for LIBASSUAN - version >= $min_libassuan_version)
ok=no
if test "$LIBASSUAN_CONFIG" != "no" ; then
req_major=`echo $min_libassuan_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
req_minor=`echo $min_libassuan_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
req_micro=`echo $min_libassuan_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
libassuan_config_version=`$LIBASSUAN_CONFIG $libassuan_config_args --version`
major=`echo $libassuan_config_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
minor=`echo $libassuan_config_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
micro=`echo $libassuan_config_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'`
if test "$major" -gt "$req_major"; then
ok=yes
else
if test "$major" -eq "$req_major"; then
if test "$minor" -gt "$req_minor"; then
ok=yes
else
if test "$minor" -eq "$req_minor"; then
if test "$micro" -ge "$req_micro"; then
ok=yes
fi
fi
fi
fi
fi
fi
if test $ok = yes; then
LIBASSUAN_CFLAGS=`$LIBASSUAN_CONFIG $libassuan_config_args --cflags`
LIBASSUAN_LIBS=`$LIBASSUAN_CONFIG $libassuan_config_args --libs`
LIBASSUAN_VERSION="$LIBASSUAN_CONFIG_VERSION"
AC_MSG_RESULT(yes)
ifelse([$2], , :, [$2])
else
LIBASSUAN_CFLAGS=""
LIBASSUAN_LIBS=""
LIBASSUAN_VERSION=""
AC_MSG_RESULT(no)
ifelse([$3], , :, [$3])
fi
AC_SUBST(LIBASSUAN_CFLAGS)
AC_SUBST(LIBASSUAN_LIBS)
AC_SUBST(LIBASSUAN_VERSION)
])

View File

@ -1,3 +1,33 @@
2009-10-20 Marcus Brinkmann <marcus@g10code.de>
* Makefile.am (assuan_cppflags, assuan_libobjs): Removed.
(gpgsm_components): Move engine-assuan.c to ...
(assuan_components): ... this new variable.
(main_sources): Add this new variable.
(AM_CPPFLAGS): Remove $(assuan_cppflags).
(AM_CFLAGS): Add @LIBASSUAN_CFLAGS@.
(libgpgme_la_DEPENDENCIES, libgpgme_pth_la_DEPENDENCIES)
(libgpgme_glib_la_DEPENDENCIES, libgpgme_qt_la_DEPENDENCIES)
(libgpgme_pthread_la_DEPENDENCIES): Remove $(assuan_libobjs).
(libgpgme_la_LIBADD, libgpgme_pth_la_LIBADD)
(libgpgme_glib_la_LIBADD, libgpgme_qt_la_LIBADD))
(libgpgme_pthread_la_LIBADD): Replace $(assuan_libobjs) by
@LIBASSUAN_LIBS@.
* priv-io.h [!HAVE_W32_SYSTEM]: Declare _gpgme_io_recvmsg,
_gpgme_io_sendmsg, _gpgme_io_waitpid.
* engine-backend.h: Define with [ENABLE_ASSUAN] instead
of [ENABLE_GPGSM].
* posix-io.c (_gpgme_io_waitpid): Make non-static.
* util.h (ENABLE_ASSUAN): Declar _gpgme_assuan_system_hooks,
_gpgme_assuan_malloc_hooks, _gpgme_assuan_log_cb.
* engine-gpgsm.c: Don't map assuan error codes. Use
assuan_release instead of assuan_disconnect.
(map_assuan_error): Remove function.
(gpgsm_new): Use new assuan context interface.
* engine-assuan.c: Use assuan_release instead of
assuan_disconnect.
(llass_new): Use new assuan context interface.
2009-10-07 <wk@g10code.com>
* priv-io.h [W32]: Include windows.h instead of sys/socket.h.

View File

@ -60,14 +60,6 @@ else
libgpgme_version_script_cmd =
endif
if BUILD_ASSUAN
assuan_cppflags = -I$(top_srcdir)/assuan
assuan_libobjs = ../assuan/libassuan.la
else
assuan_cppflags =
assuan_libobjs =
endif
if HAVE_DOSISH_SYSTEM
system_components = w32-util.c w32-sema.c
system_components_not_extra = w32-io.c
@ -77,11 +69,17 @@ system_components_not_extra =
endif
if HAVE_GPGSM
gpgsm_components = engine-gpgsm.c engine-assuan.c
gpgsm_components = engine-gpgsm.c
else
gpgsm_components =
endif
if HAVE_ASSUAN
assuan_components = assuan-support.c engine-assuan.c
else
assuan_components =
endif
if HAVE_GPGCONF
gpgconf_components = engine-gpgconf.c
else
@ -106,7 +104,8 @@ main_sources = \
import.c export.c genkey.c delete.c edit.c getauditlog.c \
opassuan.c \
engine.h engine-backend.h engine.c engine-gpg.c status-table.h \
$(gpgsm_components) $(gpgconf_components) gpgconf.c \
$(gpgsm_components) $(assuan_components) $(gpgconf_components) \
gpgconf.c \
sema.h priv-io.h $(system_components) dirinfo.c \
debug.c debug.h gpgme.c version.c error.c
@ -136,9 +135,9 @@ endif
# We use a global CFLAGS and CPPFLAGS setting for all library
# versions, because then every object file is only compiled once.
AM_CPPFLAGS = $(assuan_cppflags) @GPG_ERROR_CFLAGS@ @PTH_CPPFLAGS@ \
AM_CPPFLAGS = @GPG_ERROR_CFLAGS@ @PTH_CPPFLAGS@ \
@QT4_CORE_CFLAGS@
AM_CFLAGS = @PTH_CFLAGS@ @GLIB_CFLAGS@ @QT4_CORE_CFLAGS@
AM_CFLAGS = @LIBASSUAN_CFLAGS@ @PTH_CFLAGS@ @GLIB_CFLAGS@ @QT4_CORE_CFLAGS@
if HAVE_W32_SYSTEM
@ -185,33 +184,30 @@ endif
libgpgme_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) $(export_symbols) \
$(libgpgme_version_script_cmd) -version-info \
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
libgpgme_la_DEPENDENCIES = $(assuan_libobjs) \
@LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
libgpgme_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \
libgpgme_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
libgpgme_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
@GPG_ERROR_LIBS@ @NETLIBS@
libgpgme_pthread_la_LDFLAGS = $(libgpgme_version_script_cmd) -version-info \
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
libgpgme_pthread_la_DEPENDENCIES = $(assuan_libobjs) \
@LTLIBOBJS@ $(srcdir)/libgpgme.vers
libgpgme_pthread_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \
libgpgme_pthread_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers
libgpgme_pthread_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
-lpthread @GPG_ERROR_LIBS@ @NETLIBS@
libgpgme_pth_la_LDFLAGS = @PTH_LDFLAGS@ \
$(libgpgme_version_script_cmd) -version-info \
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
libgpgme_pth_la_DEPENDENCIES = $(assuan_libobjs) \
@LTLIBOBJS@ $(srcdir)/libgpgme.vers
libgpgme_pth_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \
libgpgme_pth_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers
libgpgme_pth_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
@PTH_LIBS@ @GPG_ERROR_LIBS@ @NETLIBS@
if BUILD_W32_GLIB
libgpgme_glib_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) \
$(export_symbols) $(libgpgme_version_script_cmd) -version-info \
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
libgpgme_glib_la_DEPENDENCIES = $(assuan_libobjs) \
@LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
libgpgme_glib_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \
libgpgme_glib_la_DEPENDENCIES = @LTLIBOBJS@ \
$(srcdir)/libgpgme.vers $(gpgme_deps)
libgpgme_glib_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
@GPG_ERROR_LIBS@ @GLIB_LIBS@ @NETLIBS@
endif
@ -219,9 +215,8 @@ if BUILD_W32_QT
libgpgme_qt_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) \
$(export_symbols) $(libgpgme_version_script_cmd) -version-info \
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
libgpgme_qt_la_DEPENDENCIES = $(assuan_libobjs) \
@LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
libgpgme_qt_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \
libgpgme_qt_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
libgpgme_qt_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
@GPG_ERROR_LIBS@ @QT4_CORE_LIBS@ @NETLIBS@
endif

View File

@ -161,7 +161,7 @@ llass_cancel (void *engine)
if (llass->assuan_ctx)
{
assuan_disconnect (llass->assuan_ctx);
assuan_release (llass->assuan_ctx);
llass->assuan_ctx = NULL;
}
@ -213,7 +213,10 @@ llass_new (void **engine, const char *file_name, const char *home_dir)
llass->opt.gpg_agent = 1;
}
err = assuan_socket_connect (&llass->assuan_ctx, file_name, 0);
err = assuan_new (&llass->assuan_ctx);
if (err)
goto leave;
err = assuan_socket_connect (llass->assuan_ctx, file_name, 0);
if (err)
goto leave;

View File

@ -129,7 +129,7 @@ extern struct engine_ops _gpgme_engine_ops_gpgsm; /* CMS. */
#ifdef ENABLE_GPGCONF
extern struct engine_ops _gpgme_engine_ops_gpgconf; /* gpg-conf. */
#endif
#ifdef ENABLE_GPGSM /* If this is enabled we also have assuan support. */
#ifdef ENABLE_ASSUAN
extern struct engine_ops _gpgme_engine_ops_assuan; /* Low-level Assuan. */
#endif

View File

@ -171,132 +171,6 @@ close_notify_handler (int fd, void *opaque)
}
static gpgme_error_t
map_assuan_error (gpg_error_t err)
{
if (!err)
return 0;
if (err == -1)
return gpg_error (GPG_ERR_INV_ENGINE);
/* New code will use gpg_error_t values. */
if (gpg_err_source (err))
return (gpgme_error_t) err;
/* Legacy code will use old values. */
switch (err)
{
case ASSUAN_No_Error:
return gpg_error (GPG_ERR_NO_ERROR);
case ASSUAN_General_Error:
return gpg_error (GPG_ERR_GENERAL);
case ASSUAN_Out_Of_Core:
return gpg_error (GPG_ERR_ENOMEM);
case ASSUAN_Invalid_Value:
return gpg_error (GPG_ERR_INV_VALUE);
case ASSUAN_Timeout:
return gpg_error (GPG_ERR_ETIMEDOUT);
case ASSUAN_Read_Error:
return gpg_error (GPG_ERR_GENERAL);
case ASSUAN_Write_Error:
return gpg_error (GPG_ERR_GENERAL);
case ASSUAN_Problem_Starting_Server:
case ASSUAN_Not_A_Server:
case ASSUAN_Not_A_Client:
case ASSUAN_Nested_Commands:
case ASSUAN_No_Data_Callback:
case ASSUAN_No_Inquire_Callback:
case ASSUAN_Connect_Failed:
case ASSUAN_Accept_Failed:
case ASSUAN_Invalid_Command:
case ASSUAN_Unknown_Command:
case ASSUAN_Syntax_Error:
case ASSUAN_Parameter_Error:
case ASSUAN_Parameter_Conflict:
case ASSUAN_No_Input:
case ASSUAN_No_Output:
case ASSUAN_No_Data_Available:
case ASSUAN_Too_Much_Data:
case ASSUAN_Inquire_Unknown:
case ASSUAN_Inquire_Error:
case ASSUAN_Invalid_Option:
case ASSUAN_Unexpected_Status:
case ASSUAN_Unexpected_Data:
case ASSUAN_Invalid_Status:
return gpg_error (GPG_ERR_ASSUAN);
case ASSUAN_Invalid_Response:
return gpg_error (GPG_ERR_INV_RESPONSE);
case ASSUAN_Not_Implemented:
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
case ASSUAN_Line_Too_Long:
return gpg_error (GPG_ERR_LINE_TOO_LONG);
case ASSUAN_Line_Not_Terminated:
return gpg_error (GPG_ERR_INCOMPLETE_LINE);
case ASSUAN_Canceled:
return gpg_error (GPG_ERR_CANCELED);
case ASSUAN_Unsupported_Algorithm:
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
case ASSUAN_Server_Resource_Problem:
return gpg_error (GPG_ERR_RESOURCE_LIMIT);
case ASSUAN_Server_IO_Error:
return gpg_error (GPG_ERR_GENERAL);
case ASSUAN_Server_Bug:
return gpg_error (GPG_ERR_BUG);
case ASSUAN_Invalid_Data:
return gpg_error (GPG_ERR_INV_DATA);
case ASSUAN_Invalid_Index:
return gpg_error (GPG_ERR_INV_INDEX);
case ASSUAN_Not_Confirmed:
return gpg_error (GPG_ERR_NOT_CONFIRMED);
case ASSUAN_Bad_Certificate:
return gpg_error (GPG_ERR_BAD_CERT);
case ASSUAN_Bad_Certificate_Chain:
return gpg_error (GPG_ERR_BAD_CERT_CHAIN);
case ASSUAN_Missing_Certificate:
return gpg_error (GPG_ERR_MISSING_CERT);
case ASSUAN_Bad_Signature:
return gpg_error (GPG_ERR_BAD_SIGNATURE);
case ASSUAN_No_Agent:
return gpg_error (GPG_ERR_NO_AGENT);
case ASSUAN_Agent_Error:
return gpg_error (GPG_ERR_AGENT);
case ASSUAN_No_Public_Key:
return gpg_error (GPG_ERR_NO_PUBKEY);
case ASSUAN_No_Secret_Key:
return gpg_error (GPG_ERR_NO_SECKEY);
case ASSUAN_Invalid_Name:
return gpg_error (GPG_ERR_INV_NAME);
case ASSUAN_Cert_Revoked:
return gpg_error (GPG_ERR_CERT_REVOKED);
case ASSUAN_No_CRL_For_Cert:
return gpg_error (GPG_ERR_NO_CRL_KNOWN);
case ASSUAN_CRL_Too_Old:
return gpg_error (GPG_ERR_CRL_TOO_OLD);
case ASSUAN_Not_Trusted:
return gpg_error (GPG_ERR_NOT_TRUSTED);
case ASSUAN_Card_Error:
return gpg_error (GPG_ERR_CARD);
case ASSUAN_Invalid_Card:
return gpg_error (GPG_ERR_INV_CARD);
case ASSUAN_No_PKCS15_App:
return gpg_error (GPG_ERR_NO_PKCS15_APP);
case ASSUAN_Card_Not_Present:
return gpg_error (GPG_ERR_CARD_NOT_PRESENT);
case ASSUAN_Invalid_Id:
return gpg_error (GPG_ERR_INV_ID);
default:
return gpg_error (GPG_ERR_GENERAL);
}
}
/* This is the default inquiry callback. We use it to handle the
Pinentry notifications. */
static gpgme_error_t
@ -330,7 +204,7 @@ gpgsm_cancel (void *engine)
if (gpgsm->assuan_ctx)
{
assuan_disconnect (gpgsm->assuan_ctx);
assuan_release (gpgsm->assuan_ctx);
gpgsm->assuan_ctx = NULL;
}
@ -450,13 +324,20 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
argv[argc++] = "--server";
argv[argc++] = NULL;
err = assuan_new_ext (&gpgsm->assuan_ctx, GPG_ERR_SOURCE_GPGME,
&_gpgme_assuan_malloc_hooks, _gpgme_assuan_log_cb,
NULL);
if (err)
goto leave;
assuan_ctx_set_system_hooks (gpgsm->assuan_ctx, &_gpgme_assuan_system_hooks);
#if USE_DESCRIPTOR_PASSING
err = assuan_pipe_connect_ext
(&gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (),
(gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (),
argv, NULL, NULL, NULL, 1);
#else
err = assuan_pipe_connect
(&gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (),
(gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (),
argv, child_fds);
/* On Windows, handles are inserted in the spawned process with
@ -504,10 +385,7 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
NULL, NULL, NULL);
free (optstr);
if (err)
{
err = map_assuan_error (err);
goto leave;
}
goto leave;
}
if (isatty (1))
@ -531,10 +409,7 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
NULL, NULL, NULL);
free (optstr);
if (err)
{
err = map_assuan_error (err);
goto leave;
}
goto leave;
err = _gpgme_getenv ("TERM", &dft_ttytype);
if (err)
@ -553,10 +428,7 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
NULL, NULL, NULL, NULL);
free (optstr);
if (err)
{
err = map_assuan_error (err);
goto leave;
}
goto leave;
}
}
}
@ -662,8 +534,6 @@ gpgsm_set_locale (void *engine, int category, const char *value)
err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL,
NULL, NULL, NULL, NULL);
free (optstr);
if (err)
err = map_assuan_error (err);
}
return err;
@ -684,13 +554,13 @@ gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd,
err = assuan_write_line (ctx, cmd);
if (err)
return map_assuan_error (err);
return err;
do
{
err = assuan_read_line (ctx, &line, &linelen);
if (err)
return map_assuan_error (err);
return err;
if (*line == '#' || !linelen)
continue;
@ -702,7 +572,7 @@ gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd,
else if (linelen >= 4
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
&& line[3] == ' ')
err = map_assuan_error (atoi (&line[4]));
err = atoi (&line[4]);
else if (linelen >= 2
&& line[0] == 'S' && line[1] == ' ')
{
@ -891,7 +761,6 @@ parse_status (const char *name)
static gpgme_error_t
status_handler (void *opaque, int fd)
{
gpg_error_t assuan_err;
gpgme_error_t err = 0;
engine_gpgsm_t gpgsm = opaque;
char *line;
@ -899,23 +768,22 @@ status_handler (void *opaque, int fd)
do
{
assuan_err = assuan_read_line (gpgsm->assuan_ctx, &line, &linelen);
if (assuan_err)
err = assuan_read_line (gpgsm->assuan_ctx, &line, &linelen);
if (err)
{
/* Try our best to terminate the connection friendly. */
/* assuan_write_line (gpgsm->assuan_ctx, "BYE"); */
err = map_assuan_error (assuan_err);
TRACE3 (DEBUG_CTX, "gpgme:status_handler", gpgsm,
"fd 0x%x: error from assuan (%d) getting status line : %s",
fd, assuan_err, gpg_strerror (err));
fd, err, gpg_strerror (err));
}
else if (linelen >= 3
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
&& (line[3] == '\0' || line[3] == ' '))
{
if (line[3] == ' ')
err = map_assuan_error (atoi (&line[4]));
else
err = atoi (&line[4]);
if (! err)
err = gpg_error (GPG_ERR_GENERAL);
TRACE2 (DEBUG_CTX, "gpgme:status_handler", gpgsm,
"fd 0x%x: ERR line - mapped to: %s",
@ -1174,7 +1042,7 @@ start (engine_gpgsm_t gpgsm, const char *command)
err = add_io_cb (gpgsm, &gpgsm->message_cb, _gpgme_data_outbound_handler);
if (!err)
err = map_assuan_error (assuan_write_line (gpgsm->assuan_ctx, command));
err = assuan_write_line (gpgsm->assuan_ctx, command);
if (!err)
gpgsm_io_event (gpgsm, GPGME_EVENT_START, NULL);

View File

@ -278,7 +278,7 @@ get_max_fds (void)
}
static int
int
_gpgme_io_waitpid (int pid, int hang, int *r_status, int *r_signal)
{
int status;

View File

@ -92,4 +92,10 @@ int _gpgme_io_fd2str (char *buf, int buflen, int fd);
(in engine-gpgsm.c). */
int _gpgme_io_dup (int fd);
#ifndef HAVE_W32_SYSTEM
int _gpgme_io_recvmsg (int fd, struct msghdr *msg, int flags);
int _gpgme_io_sendmsg (int fd, const struct msghdr *msg, int flags);
int _gpgme_io_waitpid (int pid, int hang, int *r_status, int *r_signal);
#endif
#endif /* IO_H */

View File

@ -124,4 +124,14 @@ const char *_gpgme_get_w32spawn_path (void);
#define GPG_ERR_NOT_OPERATIONAL 176
#endif
#ifdef ENABLE_ASSUAN
#include <assuan.h>
/* System hooks for assuan integration. */
extern struct assuan_system_hooks _gpgme_assuan_system_hooks;
extern struct assuan_malloc_hooks _gpgme_assuan_malloc_hooks;
int _gpgme_assuan_log_cb (assuan_context_t ctx, void *hook,
unsigned int cat, const char *msg);
#endif
#endif /* UTIL_H */