1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

Changes to make use of code taken from libassuan. This replaces the

old ad-hoc connection code to gpg-agent.  We do need this for the
forthcoming diversion of card code to an already running gpg-agent
with card-support.
This commit is contained in:
Werner Koch 2005-04-05 17:09:13 +00:00
parent 727cda9758
commit 80f4424658
23 changed files with 2432 additions and 619 deletions

View file

@ -1,3 +1,22 @@
2005-04-04 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* 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 <dshaw@jabberwocky.com>
* ttyio.c (tty_enable_completion, tty_disable_completion): Enable

View file

@ -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

480
util/assuan-buffer.c Normal file
View file

@ -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;
}

280
util/assuan-client.c Normal file
View file

@ -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;
}

95
util/assuan-connect.c Normal file
View file

@ -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;
}

243
util/assuan-defs.h Normal file
View file

@ -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*/

104
util/assuan-errors.c Normal file
View file

@ -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;
}

115
util/assuan-logging.c Normal file
View file

@ -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*/

View file

@ -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;
}

96
util/assuan-socket.c Normal file
View file

@ -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
}

170
util/assuan-util.c Normal file
View file

@ -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);
}
}
}

29
util/isascii.c Normal file
View file

@ -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);
}

View file

@ -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);
}