aboutsummaryrefslogtreecommitdiffstats
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--util/ChangeLog19
-rw-r--r--util/Makefile.am18
-rw-r--r--util/assuan-buffer.c480
-rw-r--r--util/assuan-client.c280
-rw-r--r--util/assuan-connect.c95
-rw-r--r--util/assuan-defs.h243
-rw-r--r--util/assuan-errors.c104
-rw-r--r--util/assuan-logging.c115
-rw-r--r--util/assuan-socket-connect.c190
-rw-r--r--util/assuan-socket.c96
-rw-r--r--util/assuan-util.c170
-rw-r--r--util/isascii.c29
-rw-r--r--util/memory.c53
13 files changed, 1865 insertions, 27 deletions
diff --git a/util/ChangeLog b/util/ChangeLog
index 52b9c317b..b6f35d3f4 100644
--- a/util/ChangeLog
+++ b/util/ChangeLog
@@ -1,3 +1,22 @@
+2005-04-04 Werner Koch <[email protected]>
+
+ * memory.c (xcalloc, xcalloc_secure): New wrappers.
+
+ * assuan-client.c (assuan_transact): Factored all code out to ..
+ (assuan_transact2): .. new. Add arg OKAY_CB. Wipe the memory
+ processed though that callback.
+
+2005-03-31 Werner Koch <[email protected]>
+
+ * isascii.c: New. This is an autoconf replacement function.
+
+ * Makefile.am (assuan_source): New. Only used when agent support
+ has been requested.
+ * assuan-buffer.c, assuan-client.c, assuan-defs.h,
+ * assuan-errors.c, assuan-logging.c, assuan-socket-connect.c,
+ * assuan-socket.c, assuan-util.c, assuan-connect.c: New. Taken
+ from libassuan 0.6.9 and adjusted for our limited use of Assuan.
+
2005-03-18 David Shaw <[email protected]>
* ttyio.c (tty_enable_completion, tty_disable_completion): Enable
diff --git a/util/Makefile.am b/util/Makefile.am
index 973f36c10..cb241da3f 100644
--- a/util/Makefile.am
+++ b/util/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+# Copyright (C) 1998, 1999, 2000, 2001, 2005 Free Software Foundation, Inc.
#
# This file is part of GnuPG.
#
@@ -22,12 +22,24 @@ INCLUDES = -I.. -I$(top_srcdir)/include -I$(top_srcdir)/intl
noinst_LIBRARIES = libutil.a
-EXTRA_libutil_a_SOURCES = regcomp.c regex.c regexec.c regex_internal.c regex_internal.h
+EXTRA_libutil_a_SOURCES = regcomp.c regex.c regexec.c regex_internal.c \
+ regex_internal.h
+
+# We build the assuan support only if it has been requested.
+if ENABLE_AGENT_SUPPORT
+assuan_source = assuan-buffer.c assuan-client.c assuan-defs.h \
+ assuan-errors.c assuan-logging.c assuan-socket-connect.c \
+ assuan-connect.c assuan-socket.c assuan-util.c
+else
+assuan_source =
+endif
+
#libutil_a_LDFLAGS =
libutil_a_SOURCES = logger.c fileutil.c miscutil.c strgutil.c \
ttyio.c argparse.c memory.c secmem.c errors.c iobuf.c \
- dotlock.c http.c srv.h srv.c simple-gettext.c w32reg.c
+ dotlock.c http.c srv.h srv.c simple-gettext.c \
+ w32reg.c $(assuan_source)
libutil_a_DEPENDENCIES = @LIBOBJS@ @REGEX_O@
# LIBOBJS is for the replacement functions
diff --git a/util/assuan-buffer.c b/util/assuan-buffer.c
new file mode 100644
index 000000000..47f4e189e
--- /dev/null
+++ b/util/assuan-buffer.c
@@ -0,0 +1,480 @@
+/* assuan-buffer.c - read and send data
+ * Copyright (C) 2001, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* Please note that this is a stripped down and modified version of
+ the orginal Assuan code from libassuan. */
+
+
+#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"
+
+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. */
+static int
+readaline (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;
+}
+
+
+int
+_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 -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 = readaline (ctx, line + atticlen,
+ LINELENGTH - atticlen, &nread, &ctx->inbound.eof);
+ }
+ }
+ else
+ /* No pending data. */
+ rc = readaline (ctx, line, LINELENGTH,
+ &nread, &ctx->inbound.eof);
+ if (rc)
+ {
+ if (ctx->log_fp)
+ fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [Error: %s]\n",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx, strerror (errno));
+ return ASSUAN_Read_Error;
+ }
+ if (!nread)
+ {
+ assert (ctx->inbound.eof);
+ if (ctx->log_fp)
+ fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [EOF]\n",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx);
+ return -1;
+ }
+
+ ctx->inbound.attic.pending = 0;
+ nread += atticlen;
+
+ if (! endp)
+ endp = memchr (line, '\n', nread);
+
+ if (endp)
+ {
+ 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;
+ if (ctx->log_fp)
+ {
+ fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- ",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx);
+ 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.%p] DBG: <- [Invalid line]\n",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx);
+ *line = 0;
+ ctx->inbound.linelen = 0;
+ return 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_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)
+{
+ int rc = 0;
+ size_t prefixlen = prefix? strlen (prefix):0;
+
+ /* Make sure that the line is short enough. */
+ if (len + prefixlen + 2 > ASSUAN_LINELENGTH)
+ {
+ if (ctx->log_fp)
+ fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> "
+ "[supplied line too long -truncated]\n",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx);
+ if (prefixlen > 5)
+ prefixlen = 5;
+ if (len > ASSUAN_LINELENGTH - prefixlen - 2)
+ len = ASSUAN_LINELENGTH - prefixlen - 2 - 1;
+ }
+
+ /* Fixme: we should do some kind of line buffering. */
+ if (ctx->log_fp)
+ {
+ fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx);
+ if (ctx->confidential)
+ fputs ("[Confidential data not shown]", ctx->log_fp);
+ else
+ _assuan_log_print_buffer (ctx->log_fp, line, len);
+ putc ('\n', ctx->log_fp);
+ }
+
+ if (prefixlen)
+ {
+ rc = writen (ctx, prefix, prefixlen);
+ if (rc)
+ rc = ASSUAN_Write_Error;
+ }
+ if (!rc)
+ {
+ rc = writen (ctx, line, len);
+ if (rc)
+ rc = ASSUAN_Write_Error;
+ if (!rc)
+ {
+ rc = writen (ctx, "\n", 1);
+ if (rc)
+ rc = 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_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.%p] DBG: -> "
+ "[supplied line contained a LF -truncated]\n",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx);
+
+ 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)
+ {
+ /* insert data line header */
+ if (!linelen)
+ {
+ *line++ = 'D';
+ *line++ = ' ';
+ linelen += 2;
+ }
+
+ /* copy data, keep some 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--;
+ }
+
+ if (linelen >= LINELENGTH-2-2)
+ {
+ if (ctx->log_fp)
+ {
+ fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx);
+
+ 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 (writen (ctx, ctx->outbound.data.line, linelen))
+ {
+ ctx->outbound.data.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;
+
+ if (ctx->outbound.data.error)
+ return 0;
+
+ line = ctx->outbound.data.line;
+ linelen = ctx->outbound.data.linelen;
+ line += linelen;
+ if (linelen)
+ {
+ if (ctx->log_fp)
+ {
+ fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx);
+ 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 (writen (ctx, ctx->outbound.data.line, linelen))
+ {
+ ctx->outbound.data.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.
+ *
+ * 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_Invalid_Value;
+ if (!buffer && length)
+ return 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, "END");
+ }
+ else
+ {
+ _assuan_cookie_write_data (ctx, buffer, length);
+ if (ctx->outbound.data.error)
+ return ctx->outbound.data.error;
+ }
+
+ return 0;
+}
+
diff --git a/util/assuan-client.c b/util/assuan-client.c
new file mode 100644
index 000000000..08ea0f6cc
--- /dev/null
+++ b/util/assuan-client.c
@@ -0,0 +1,280 @@
+/* assuan-client.c - client functions
+ * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* Please note that this is a stripped down and modified version of
+ the orginal Assuan code from libassuan. */
+
+#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_Invalid_Response;
+ return rc;
+}
+
+
+
+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)
+{
+ return assuan_transact2 (ctx, command,
+ data_cb, data_cb_arg,
+ inquire_cb, inquire_cb_arg,
+ status_cb, status_cb_arg,
+ NULL, NULL);
+}
+
+
+/**
+ * assuan_transact2:
+ * @ctx: The Assuan context
+ * @command: Coimmand line to be send to 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
+ * @okay_cb: Callback function for the final OK response
+ * @okay_cb_arg: first argument passed to @okay_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.
+ **/
+assuan_error_t
+assuan_transact2 (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_error_t (*okay_cb)(void*, const char *),
+ void *okay_cb_arg)
+{
+ int rc, okay, off;
+ unsigned 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 < 100)
+ rc = ASSUAN_Server_Fault;
+ }
+ else if (okay == 1) /* Received OK. */
+ {
+ if (okay_cb)
+ {
+ rc = okay_cb (okay_cb_arg, line);
+ /* We better wipe out the buffer after processing it. This
+ is no real guarantee that it won't get swapped out but at
+ least for the standard cases we can make sure that a
+ passphrase returned with the OK line is rendered
+ unreadable. In fact the current Assuan interface suffers
+ from the problem that it is not possible to do assuan I/O
+ through secure memory. There is no easy solution given
+ the current implementation but we need to address it
+ sooner or later. The problem was introduced with
+ gpg-agent's GET_PASPHRASE command but it might also make
+ sense to have a way to convey sessions keys through
+ secured memory. Note that the old implementation in gpg
+ for accessing the passphrase in fact used secure memory
+ but had the drawback of using a limited and not fully
+ conforming Assuan implementation - given that pinentry
+ and gpg-agent neither use secured memory for Assuan I/O,
+ it is negligible to drop the old implementation in gpg's
+ passphrase.c and use the wipememory workaround here. */
+ memset (line, 0, strlen (line));
+ }
+ }
+ else if (okay == 2)
+ {
+ if (!data_cb)
+ rc = ASSUAN_No_Data_Callback;
+ else
+ {
+ unsigned 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_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_No_Data_Callback;
+ else
+ {
+ rc = data_cb (data_cb_arg, NULL, 0);
+ if (!rc)
+ goto again;
+ }
+ }
+
+ return rc;
+}
+
diff --git a/util/assuan-connect.c b/util/assuan-connect.c
new file mode 100644
index 000000000..52c9aa00f
--- /dev/null
+++ b/util/assuan-connect.c
@@ -0,0 +1,95 @@
+/* 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* Please note that this is a stripped down and modified version of
+ the orginal Assuan code from libassuan. */
+
+#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"
+
+/* Create a new context. */
+int
+_assuan_new_context (assuan_context_t *r_ctx)
+{
+ assuan_context_t ctx;
+
+ *r_ctx = NULL;
+ ctx = xcalloc (1, sizeof *ctx);
+
+ ctx->input_fd = -1;
+ ctx->output_fd = -1;
+
+ ctx->inbound.fd = -1;
+ ctx->outbound.fd = -1;
+ ctx->io = NULL;
+
+ ctx->listen_fd = -1;
+ *r_ctx = ctx;
+ return 0;
+}
+
+
+void
+_assuan_release_context (assuan_context_t ctx)
+{
+ if (ctx)
+ {
+ xfree (ctx->hello_line);
+ xfree (ctx->okay_line);
+ xfree (ctx);
+ }
+}
+
+
+/* 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. */
+pid_t
+assuan_get_pid (assuan_context_t ctx)
+{
+ return (ctx && ctx->pid)? ctx->pid : -1;
+}
+
diff --git a/util/assuan-defs.h b/util/assuan-defs.h
new file mode 100644
index 000000000..06400d836
--- /dev/null
+++ b/util/assuan-defs.h
@@ -0,0 +1,243 @@
+/* assuan-defs.c - Internal definitions to Assuan
+ * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
+ * Copyright (C) 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* Please note that this is a stripped down and modified version of
+ the orginal Assuan code from libassuan. */
+
+
+#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"
+#include "memory.h"
+
+#ifndef HAVE_W32_SYSTEM
+#define DIRSEP_C '/'
+#else
+#define DIRSEP_C '\\'
+#endif
+
+#ifdef HAVE_W32_SYSTEM
+#define AF_LOCAL AF_UNIX
+/* We need to prefix the structure with a sockaddr_in header so we can
+ use it later for sendto and recvfrom. */
+struct sockaddr_un
+{
+ short sun_family;
+ unsigned short sun_port;
+ struct in_addr sun_addr;
+ char sun_path[108-2-4]; /* Path name. */
+};
+
+/* 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);
+};
+
+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, int);
+ /* Receive a file descriptor. */
+ assuan_error_t (*receivefd) (assuan_context_t, int *);
+};
+
+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*/
+
+ int confidential;
+ int is_server; /* set if this is context belongs to a server */
+ int in_inquire;
+ char *hello_line;
+ char *okay_line; /* see assan_set_okay_line() */
+
+ void *user_pointer; /* for assuan_[gs]et_pointer () */
+
+ FILE *log_fp;
+
+ struct {
+ int 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 {
+ int 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 the pid of the peer. */
+ int listen_fd; /* The fd we are listening on (used by socket servers) */
+ int connected_fd; /* helper */
+
+ /* Used for Unix domain sockets. */
+ struct sockaddr_un myaddr;
+ struct sockaddr_un serveraddr;
+ /* When reading from datagram sockets, we must read an entire
+ message at a time. This means that we have to do our own
+ buffering to be able to get the semantics of read. */
+ void *domainbuffer;
+ /* Offset of start of buffer. */
+ int domainbufferoffset;
+ /* Bytes buffered. */
+ int domainbuffersize;
+ /* Memory allocated. */
+ int domainbufferallocated;
+
+ int *pendingfds;
+ int pendingfdscount;
+
+ 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 *);
+
+ int input_fd; /* set by INPUT command */
+ int output_fd; /* set by 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-domain-connect.c --*/
+/* 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_domain_init (assuan_context_t *r_ctx,
+ int rendezvousfd,
+ pid_t peer);
+
+/*-- assuan-handler.c --*/
+int _assuan_register_std_commands (assuan_context_t ctx);
+
+/*-- assuan-buffer.c --*/
+int _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-util.c --*/
+
+#define set_error(c,e,t) assuan_set_error ((c), ASSUAN_ ## e, (t))
+
+void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length);
+void _assuan_log_sanitized_string (const char *string);
+
+#ifdef HAVE_W32_SYSTEM
+const char *_assuan_w32_strerror (int ec);
+#define w32_strerror(e) _assuan_w32_strerror ((e))
+#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
+ ;
+
+/*-- assuan-io.c --*/
+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);
+
+/*-- assuan-socket.c --*/
+int _assuan_close (int fd);
+int _assuan_sock_new (int domain, int type, int proto);
+int _assuan_sock_connect (int sockfd, struct sockaddr *addr, int addrlen);
+
+#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*/
+
+#endif /*ASSUAN_DEFS_H*/
+
diff --git a/util/assuan-errors.c b/util/assuan-errors.c
new file mode 100644
index 000000000..01f718ca9
--- /dev/null
+++ b/util/assuan-errors.c
@@ -0,0 +1,104 @@
+/* assuan-errors.c - error codes
+ * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* Please note that this is a stripped down and modified version of
+ the orginal Assuan code from libassuan. */
+
+#include <stdio.h>
+#include "assuan.h"
+
+/* This function returns a textual representaion of the given error
+ code. 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)
+ {
+ case ASSUAN_No_Error: s="no error"; break;
+ case ASSUAN_General_Error: s="general error"; break;
+ case ASSUAN_Out_Of_Core: s="out of core"; break;
+ case ASSUAN_Invalid_Value: s="invalid value"; break;
+ case ASSUAN_Timeout: s="timeout"; break;
+ case ASSUAN_Read_Error: s="read error"; break;
+ case ASSUAN_Write_Error: s="write error"; break;
+ case ASSUAN_Problem_Starting_Server: s="problem starting server"; break;
+ case ASSUAN_Not_A_Server: s="not a server"; break;
+ case ASSUAN_Not_A_Client: s="not a client"; break;
+ case ASSUAN_Nested_Commands: s="nested commands"; break;
+ case ASSUAN_Invalid_Response: s="invalid response"; break;
+ case ASSUAN_No_Data_Callback: s="no data callback"; break;
+ case ASSUAN_No_Inquire_Callback: s="no inquire callback"; break;
+ case ASSUAN_Connect_Failed: s="connect failed"; break;
+ case ASSUAN_Accept_Failed: s="accept failed"; break;
+ case ASSUAN_Not_Implemented: s="not implemented"; break;
+ case ASSUAN_Server_Fault: s="server fault"; break;
+ case ASSUAN_Invalid_Command: s="invalid command"; break;
+ case ASSUAN_Unknown_Command: s="unknown command"; break;
+ case ASSUAN_Syntax_Error: s="syntax error"; break;
+ case ASSUAN_Parameter_Error: s="parameter error"; break;
+ case ASSUAN_Parameter_Conflict: s="parameter conflict"; break;
+ case ASSUAN_Line_Too_Long: s="line too long"; break;
+ case ASSUAN_Line_Not_Terminated: s="line not terminated"; break;
+ case ASSUAN_No_Input: s="no input"; break;
+ case ASSUAN_No_Output: s="no output"; break;
+ case ASSUAN_Canceled: s="canceled"; break;
+ case ASSUAN_Unsupported_Algorithm: s="unsupported algorithm"; break;
+ case ASSUAN_Server_Resource_Problem: s="server resource problem"; break;
+ case ASSUAN_Server_IO_Error: s="server io error"; break;
+ case ASSUAN_Server_Bug: s="server bug"; break;
+ case ASSUAN_No_Data_Available: s="no data available"; break;
+ case ASSUAN_Invalid_Data: s="invalid data"; break;
+ case ASSUAN_Unexpected_Command: s="unexpected command"; break;
+ case ASSUAN_Too_Much_Data: s="too much data"; break;
+ case ASSUAN_Inquire_Unknown: s="inquire unknown"; break;
+ case ASSUAN_Inquire_Error: s="inquire error"; break;
+ case ASSUAN_Invalid_Option: s="invalid option"; break;
+ case ASSUAN_Invalid_Index: s="invalid index"; break;
+ case ASSUAN_Unexpected_Status: s="unexpected status"; break;
+ case ASSUAN_Unexpected_Data: s="unexpected data"; break;
+ case ASSUAN_Invalid_Status: s="invalid status"; break;
+ case ASSUAN_Locale_Problem: s="locale problem"; break;
+ case ASSUAN_Not_Confirmed: s="not confirmed"; break;
+ case ASSUAN_USER_ERROR_FIRST: s="user error first"; break;
+ case ASSUAN_USER_ERROR_LAST: s="user error last"; break;
+ default:
+ {
+ unsigned int source, code;
+
+ source = ((err >> 24) & 0xff);
+ code = (err & 0x00ffffff);
+ if (source) /* Assume this is an libgpg-error. */
+ sprintf (buf, "ec=%u.%u", source, code );
+ else
+ sprintf (buf, "ec=%d", err );
+ s=buf; break;
+ }
+ }
+
+ return s;
+}
+
diff --git a/util/assuan-logging.c b/util/assuan-logging.c
new file mode 100644
index 000000000..6663e8114
--- /dev/null
+++ b/util/assuan-logging.c
@@ -0,0 +1,115 @@
+/* assuan-logging.c - Default logging function.
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* Please note that this is a stripped down and modified version of
+ the orginal Assuan code from libassuan. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#ifdef HAVE_W32_SYSTEM
+#include <windows.h>
+#endif /*HAVE_W32_SYSTEM*/
+
+#include "assuan-defs.h"
+
+static char prefix_buffer[80];
+static FILE *_assuan_log;
+
+void
+_assuan_set_default_log_stream (FILE *fp)
+{
+ if (!_assuan_log)
+ _assuan_log = fp;
+}
+
+void
+assuan_set_assuan_log_stream (FILE *fp)
+{
+ _assuan_log = 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;
+
+ fp = assuan_get_assuan_log_stream ();
+ prf = assuan_get_assuan_log_prefix ();
+ if (*prf)
+ {
+ fputs (prf, fp);
+ fputs (": ", fp);
+ }
+
+ va_start (arg_ptr, format);
+ vfprintf (fp, format, arg_ptr );
+ va_end (arg_ptr);
+}
+
+
+
+#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;
+}
+#endif /*HAVE_W32_SYSTEM*/
diff --git a/util/assuan-socket-connect.c b/util/assuan-socket-connect.c
new file mode 100644
index 000000000..003859147
--- /dev/null
+++ b/util/assuan-socket-connect.c
@@ -0,0 +1,190 @@
+/* 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* Please note that this is a stripped down and modified version of
+ the orginal Assuan code from libassuan. */
+
+#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 != -1)
+ {
+ _assuan_close (ctx->inbound.fd);
+ }
+ ctx->inbound.fd = -1;
+ ctx->outbound.fd = -1;
+ return 0;
+}
+
+static void
+do_deinit (assuan_context_t ctx)
+{
+ do_finish (ctx);
+}
+
+
+static ssize_t
+simple_read (assuan_context_t ctx, void *buffer, size_t size)
+{
+#ifndef HAVE_W32_SYSTEM
+ return read (ctx->inbound.fd, buffer, size);
+#else
+ return recv (ctx->inbound.fd, buffer, size, 0);
+#endif
+}
+
+static ssize_t
+simple_write (assuan_context_t ctx, const void *buffer, size_t size)
+{
+#ifndef HAVE_W32_SYSTEM
+ return write (ctx->outbound.fd, buffer, size);
+#else
+ return send (ctx->outbound.fd, buffer, size, 0);
+#endif
+}
+
+
+/* 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)
+{
+ static struct assuan_io io = { simple_read, simple_write };
+
+ assuan_error_t err;
+ assuan_context_t ctx;
+ int fd;
+ struct sockaddr_un srvr_addr;
+ size_t len;
+ const char *s;
+
+ if (!r_ctx || !name)
+ return ASSUAN_Invalid_Value;
+ *r_ctx = NULL;
+
+ /* We require that the name starts with a slash, so that we can
+ alter reuse this function for other socket types. To make things
+ easier we allow an optional dirver prefix. */
+ s = name;
+ if (*s && s[1] == ':')
+ s += 2;
+ if (*s != DIRSEP_C && *s != '/')
+ return ASSUAN_Invalid_Value;
+
+ if (strlen (name)+1 >= sizeof srvr_addr.sun_path)
+ return ASSUAN_Invalid_Value;
+
+ err = _assuan_new_context (&ctx);
+ if (err)
+ return err;
+ ctx->deinit_handler = do_deinit;
+ ctx->finish_handler = do_finish;
+
+
+ fd = _assuan_sock_new (PF_LOCAL, SOCK_STREAM, 0);
+ if (fd == -1)
+ {
+ _assuan_log_printf ("can't create socket: %s\n", strerror (errno));
+ _assuan_release_context (ctx);
+ return 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_Connect_Failed;
+ }
+
+ ctx->inbound.fd = fd;
+ ctx->outbound.fd = fd;
+ ctx->io = &io;
+
+ /* 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_Connect_Failed;
+ }
+ }
+
+ if (err)
+ {
+ assuan_disconnect (ctx);
+ }
+ else
+ *r_ctx = ctx;
+ return 0;
+}
diff --git a/util/assuan-socket.c b/util/assuan-socket.c
new file mode 100644
index 000000000..080eff243
--- /dev/null
+++ b/util/assuan-socket.c
@@ -0,0 +1,96 @@
+/* assuan-socket.c
+ * Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* Please note that this is a stripped down and modified version of
+ the orginal Assuan code from libassuan. */
+
+#include <config.h>
+#include <stdio.h>
+#ifdef HAVE_W32_SYSTEM
+#include <windows.h>
+#include <io.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+#include "assuan-defs.h"
+
+int
+_assuan_close (int fd)
+{
+#ifndef HAVE_W32_SYSTEM
+ return close (fd);
+#else
+ int rc = closesocket (fd);
+ if (rc && WSAGetLastError () == WSAENOTSOCK)
+ rc = close (fd);
+ return rc;
+#endif
+}
+
+
+int
+_assuan_sock_new (int domain, int type, int proto)
+{
+#ifndef HAVE_W32_SYSTEM
+ return socket (domain, type, proto);
+#else
+ if (domain == AF_UNIX || domain == AF_LOCAL)
+ domain = AF_INET;
+ return socket (domain, type, proto);
+#endif
+}
+
+
+int
+_assuan_sock_connect (int sockfd, struct sockaddr * addr, int addrlen)
+{
+#ifndef HAVE_W32_SYSTEM
+ return connect (sockfd, addr, addrlen);
+#else
+ struct sockaddr_in myaddr;
+ struct sockaddr_un * unaddr;
+ FILE * fp;
+ int port = 0;
+
+ unaddr = (struct sockaddr_un *)addr;
+ fp = fopen (unaddr->sun_path, "rb");
+ if (!fp)
+ return -1;
+ fscanf (fp, "%d", &port);
+ fclose (fp);
+ /* XXX: set errno in this case */
+ if (port < 0 || port > 65535)
+ return -1;
+
+ myaddr.sin_family = AF_INET;
+ myaddr.sin_port = port;
+ myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+
+ /* we need this later. */
+ unaddr->sun_family = myaddr.sin_family;
+ unaddr->sun_port = myaddr.sin_port;
+ unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
+
+ return connect (sockfd, (struct sockaddr *)&myaddr, sizeof myaddr);
+#endif
+}
+
+
diff --git a/util/assuan-util.c b/util/assuan-util.c
new file mode 100644
index 000000000..a5ee0b290
--- /dev/null
+++ b/util/assuan-util.c
@@ -0,0 +1,170 @@
+/* assuan-util.c - Utility functions for Assuan
+ * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ * Copyright (C) 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* Please note that this is a stripped down and modified version of
+ the orginal Assuan code from libassuan. */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "assuan-defs.h"
+
+
+
+/* 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_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);
+ }
+}
+
+
+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;
+ }
+}
+
+/* Dump a possibly binary string (used for debugging). Distinguish
+ ascii text from binary and print it accordingly. */
+void
+_assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length)
+{
+ const unsigned char *s;
+ 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
+ {
+ putc ('[', fp);
+ for (n=0; n < length; n++, s++)
+ fprintf (fp, " %02x", *s);
+ putc (' ', fp);
+ putc (']', fp);
+ }
+}
+
+/* Log a user supplied string. Escapes non-printable before
+ printing. */
+void
+_assuan_log_sanitized_string (const char *string)
+{
+ const unsigned char *s = string;
+ FILE *fp = assuan_get_assuan_log_stream ();
+
+ if (! *s)
+ return;
+
+ 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 (*s, fp);
+ else
+ {
+ putc ('\\', fp);
+ fprintf (fp, "x%02x", *s);
+ }
+ }
+
+ if (c)
+ {
+ putc ('\\', fp);
+ putc (c, fp);
+ }
+ }
+}
+
diff --git a/util/isascii.c b/util/isascii.c
new file mode 100644
index 000000000..565c71664
--- /dev/null
+++ b/util/isascii.c
@@ -0,0 +1,29 @@
+/* isascii.c - Replacement for isascii.
+ * Copyright (C) 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+int
+isascii (int c)
+{
+ return (((c) & ~0x7f) == 0);
+}
diff --git a/util/memory.c b/util/memory.c
index c062bdd5f..f84e507dc 100644
--- a/util/memory.c
+++ b/util/memory.c
@@ -1,5 +1,5 @@
/* memory.c - memory allocation
- * Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -603,29 +603,6 @@ m_size( const void *a )
}
-#if 0 /* not used */
-/****************
- * Make a copy of the memory block at a
- */
-void *
-FNAME(copy)( const void *a FNAMEPRT )
-{
- void *b;
- size_t n;
-
- if( !a )
- return NULL;
-
- n = m_size(a); Aiiiih woher nehmen
- if( m_is_secure(a) )
- b = FNAME(alloc_secure)(n FNAMEARG);
- else
- b = FNAME(alloc)(n FNAMEARG);
- memcpy(b, a, n );
- return b;
-}
-#endif
-
char *
FNAME(strdup)( const char *a FNAMEPRT )
{
@@ -634,3 +611,31 @@ FNAME(strdup)( const char *a FNAMEPRT )
strcpy(p, a);
return p;
}
+
+
+/* Wrapper around m_alloc_clear to take the usual 2 arguments of a
+ calloc style function. */
+void *
+xcalloc (size_t n, size_t m)
+{
+ size_t nbytes;
+
+ nbytes = n * m;
+ if (m && nbytes / m != n)
+ out_of_core (nbytes, 0);
+ return m_alloc_clear (nbytes);
+}
+
+/* Wrapper around m_alloc_csecure_lear to take the usual 2 arguments
+ of a calloc style function. */
+void *
+xcalloc_secure (size_t n, size_t m)
+{
+ size_t nbytes;
+
+ nbytes = n * m;
+ if (m && nbytes / m != n)
+ out_of_core (nbytes, 1);
+ return m_alloc_secure_clear (nbytes);
+}
+