mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-21 14:47:03 +01: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:
parent
727cda9758
commit
80f4424658
11
ChangeLog
11
ChangeLog
@ -1,3 +1,14 @@
|
||||
2005-03-31 Werner Koch <wk@g10code.com>
|
||||
|
||||
* configure.ac: New option --disable-agent-support. Define
|
||||
ENABLE_AGENT_SUPPORT as AC_DEFINE and AM_CONDITIONAL.
|
||||
Disable support for card and agent with --enable-minimal.
|
||||
(AC_REPLACE_FUNCS): Add isascii.
|
||||
(g10defs.h): Define PATHSEP_C and PATHSEP_S.
|
||||
|
||||
* README: Changed the instruction on how to verify a signature to
|
||||
show a .sig extension and not the .asc we used to use ages ago.
|
||||
|
||||
2005-03-16 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* configure.ac: Move the LDAP detecting code to m4/ldap.m4.
|
||||
|
18
README
18
README
@ -81,10 +81,10 @@
|
||||
a) If you already have a trusted Version of GnuPG installed, you
|
||||
can simply check the supplied signature:
|
||||
|
||||
$ gpg --verify gnupg-x.y.z.tar.gz.asc
|
||||
$ gpg --verify gnupg-x.y.z.tar.gz.sig
|
||||
|
||||
This checks that the detached signature gnupg-x.y.z.tar.gz.asc
|
||||
is indeed a a signature of gnupg-x.y.z.tar.gz. The key used to
|
||||
This checks that the detached signature gnupg-x.y.z.tar.gz.sig
|
||||
is indeed a signature of gnupg-x.y.z.tar.gz. The key used to
|
||||
create this signature is:
|
||||
|
||||
"pub 1024D/57548DCD 1998-07-07 Werner Koch (gnupg sig) <dd9jn@gnu.org>"
|
||||
@ -584,9 +584,11 @@
|
||||
--disable-cast5, --disable-blowfish,
|
||||
--disable-aes, --disable-twofish,
|
||||
--disable-sha256, --disable-sha512,
|
||||
--without-bzip2, and --disable-exec. Configure
|
||||
command lines are read from left to right, so if
|
||||
you want to have an "almost minimal"
|
||||
--without-bzip2, --disable-exec,
|
||||
--disable-card-support and
|
||||
--disable-agent-support.
|
||||
Configure command lines are read from left to
|
||||
right, so if you want to have an "almost minimal"
|
||||
configuration, you can do (for example)
|
||||
"--enable-minimal --enable-rsa" to have RSA added
|
||||
to the minimal build.
|
||||
@ -603,6 +605,10 @@
|
||||
to include support if all required libraries are
|
||||
available.
|
||||
|
||||
--disable-agent-support
|
||||
Do not include support for the gpg-agent. The
|
||||
default is to include support.
|
||||
|
||||
--enable-selinux-support
|
||||
This prevents access to certain files and won't
|
||||
allow import or export of secret keys.
|
||||
|
1
THANKS
1
THANKS
@ -181,6 +181,7 @@ Russell Coker russell@coker.com.au
|
||||
Ryan Malayter rmalayter@bai.org
|
||||
Sam Roberts sam@cogent.ca
|
||||
Sami Tolvanen sami@tolvanen.com
|
||||
Sascha Kiefer sk@intertivity.com
|
||||
Sean MacLennan seanm@netwinder.org
|
||||
Sebastian Klemke packet@convergence.de
|
||||
Serge Munhoven munhoven@mema.ucl.ac.be
|
||||
|
44
configure.ac
44
configure.ac
@ -122,13 +122,6 @@ AC_ARG_ENABLE(selinux-support,
|
||||
AC_MSG_RESULT($selinux_support)
|
||||
|
||||
|
||||
AC_MSG_CHECKING([whether OpenPGP card support is requested])
|
||||
AC_ARG_ENABLE(card-support,
|
||||
AC_HELP_STRING([--disable-card-support],
|
||||
[disable OpenPGP card support]),
|
||||
card_support=$enableval, card_support=yes)
|
||||
AC_MSG_RESULT($card_support)
|
||||
|
||||
AC_MSG_CHECKING([whether the new iconv based code is requested])
|
||||
AC_ARG_ENABLE(gnupg-iconv,
|
||||
AC_HELP_STRING([--disable-gnupg-iconv],
|
||||
@ -158,6 +151,8 @@ use_sha256=yes
|
||||
use_sha512=yes
|
||||
use_bzip2=yes
|
||||
use_exec=yes
|
||||
card_support=yes
|
||||
agent_support=yes
|
||||
|
||||
AC_ARG_ENABLE(minimal,
|
||||
AC_HELP_STRING([--enable-minimal],[build the smallest gpg binary possible]),
|
||||
@ -170,7 +165,27 @@ AC_ARG_ENABLE(minimal,
|
||||
use_sha256=no
|
||||
use_sha512=no
|
||||
use_bzip2=no
|
||||
use_exec=no)
|
||||
use_exec=no
|
||||
card_support=no
|
||||
agent_support=no)
|
||||
|
||||
|
||||
AC_MSG_CHECKING([whether OpenPGP card support is requested])
|
||||
AC_ARG_ENABLE(card-support,
|
||||
AC_HELP_STRING([--disable-card-support],
|
||||
[disable OpenPGP card support]),
|
||||
card_support=$enableval)
|
||||
AC_MSG_RESULT($card_support)
|
||||
|
||||
|
||||
# Note that we may later disable the agent support based on the platform.
|
||||
AC_MSG_CHECKING([whether gpg-agent support is requested])
|
||||
AC_ARG_ENABLE(agent-support,
|
||||
AC_HELP_STRING([--disable-agent-support],
|
||||
[disable gpg-agent support]),
|
||||
agent_support=$enableval)
|
||||
AC_MSG_RESULT($agent_support)
|
||||
|
||||
|
||||
AC_MSG_CHECKING([whether to enable the RSA public key algorithm])
|
||||
AC_ARG_ENABLE(rsa,
|
||||
@ -471,6 +486,7 @@ case "${host}" in
|
||||
have_dosish_system=yes
|
||||
need_dlopen=no
|
||||
try_gettext="no"
|
||||
agent_support=no
|
||||
;;
|
||||
i?86-emx-os2 | i?86-*-os2*emx )
|
||||
# OS/2 with the EMX environment
|
||||
@ -478,6 +494,7 @@ case "${host}" in
|
||||
AC_DEFINE(HAVE_DRIVE_LETTERS)
|
||||
have_dosish_system=yes
|
||||
try_gettext="no"
|
||||
agent_support=no
|
||||
;;
|
||||
|
||||
i?86-*-msdosdjgpp*)
|
||||
@ -486,6 +503,7 @@ case "${host}" in
|
||||
AC_DEFINE(HAVE_DRIVE_LETTERS)
|
||||
have_dosish_system=yes
|
||||
try_gettext="no"
|
||||
agent_support=no
|
||||
;;
|
||||
|
||||
*-*-freebsd*)
|
||||
@ -754,6 +772,10 @@ if test "$card_support" = yes ; then
|
||||
AC_DEFINE(ENABLE_CARD_SUPPORT,1,[Define to include OpenPGP card support])
|
||||
fi
|
||||
|
||||
if test "$agent_support" = yes ; then
|
||||
AC_DEFINE(ENABLE_AGENT_SUPPORT,1,[Define to include gpg-agent support])
|
||||
fi
|
||||
|
||||
if test "$try_extensions" = yes ; then
|
||||
AC_DEFINE(USE_DYNAMIC_LINKING,1,[Define to enable the use of extensions])
|
||||
fi
|
||||
@ -771,6 +793,7 @@ if test "$do_backsigs" = yes ; then
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(ENABLE_CARD_SUPPORT, test "$card_support" = yes)
|
||||
AM_CONDITIONAL(ENABLE_AGENT_SUPPORT, test "$agent_support" = yes)
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
@ -841,6 +864,7 @@ AC_CHECK_FUNCS(memmove gettimeofday getrusage setrlimit clock_gettime)
|
||||
AC_CHECK_FUNCS(atexit raise getpagesize strftime nl_langinfo setlocale)
|
||||
AC_CHECK_FUNCS(waitpid wait4 sigaction sigprocmask rand pipe stat getaddrinfo)
|
||||
AC_REPLACE_FUNCS(mkdtemp timegm)
|
||||
AC_REPLACE_FUNCS(isascii)
|
||||
|
||||
AC_CHECK_TYPES([struct sigaction, sigset_t],,,[#include <signal.h>])
|
||||
|
||||
@ -1260,11 +1284,15 @@ cat >g10defs.tmp <<G10EOF
|
||||
#define EXTSEP_C '.'
|
||||
#define DIRSEP_S "\\\\"
|
||||
#define EXTSEP_S "."
|
||||
#define PATHSEP_C ';'
|
||||
#define PATHSEP_S ";"
|
||||
#else
|
||||
#define DIRSEP_C '/'
|
||||
#define EXTSEP_C '.'
|
||||
#define DIRSEP_S "/"
|
||||
#define EXTSEP_S "."
|
||||
#define PATHSEP_C ':'
|
||||
#define PATHSEP_S ":"
|
||||
#endif
|
||||
/* This is the same as VERSION, but should be overridden if the
|
||||
platform cannot handle things like dots'.' in filenames. Set
|
||||
|
@ -1,3 +1,8 @@
|
||||
2005-04-01 Werner Koch <wk@g10code.com>
|
||||
|
||||
* keygen.c (keygen_set_std_prefs): Explain the chosen order of
|
||||
AES key sizes.
|
||||
|
||||
2005-04-01 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* mainproc.c (proc_plaintext): Properly handle SIG+LITERAL
|
||||
@ -11,6 +16,24 @@
|
||||
|
||||
2005-03-31 Werner Koch <wk@g10code.com>
|
||||
|
||||
* passphrase.c (agent_open): Dropped support for W32 - is was
|
||||
never actually used. Removed support for the old non-assuan
|
||||
protocol; there has never been a matured implementation and
|
||||
gpg-agent is now arround for quite some time. Rewritten to make
|
||||
use of the Assuan code from ../util.
|
||||
(gpga_protocol_codes): Removed.
|
||||
(readn): Removed.
|
||||
(agent_close): Simplified for use with Assuan.
|
||||
(agent_get_passphrase, passphrase_clear_cache): Removed support
|
||||
for old protocol. Use only with ENABLE_CARD_SUPPORT defined.
|
||||
(agent_send_all_options): Take assuan context instead of a file
|
||||
descriptor.
|
||||
(agent_send_option): Likewise. Use assuan_transact.
|
||||
* passphrase.c (writen, readaline): Removed.
|
||||
|
||||
* g10.c (main): Print a warning if --use-agent has been used but
|
||||
it has not been build with support for it.
|
||||
|
||||
* keydb.c (keydb_add_resource): Clarify meaning of flags. Add new
|
||||
flag 4. Use log_info for errors registering the default secret key.
|
||||
* g10.c (main): Flag the default keyrings.
|
||||
|
@ -2591,6 +2591,14 @@ main( int argc, char **argv )
|
||||
"--no-literal" );
|
||||
}
|
||||
|
||||
#ifndef ENABLE_AGENT_SUPPORT
|
||||
if (opt.use_agent) {
|
||||
log_info(_("NOTE: %s is not available in this version\n"),
|
||||
"--use-agent");
|
||||
opt.use_agent = 0;
|
||||
}
|
||||
#endif /*!ENABLE_AGENT_SUPPORT*/
|
||||
|
||||
if (opt.set_filesize)
|
||||
log_info(_("NOTE: %s is not for normal use!\n"), "--set-filesize");
|
||||
if( opt.batch )
|
||||
|
777
g10/passphrase.c
777
g10/passphrase.c
@ -50,32 +50,9 @@
|
||||
#include "main.h"
|
||||
#include "i18n.h"
|
||||
#include "status.h"
|
||||
|
||||
|
||||
enum gpga_protocol_codes {
|
||||
/* Request codes */
|
||||
GPGA_PROT_GET_VERSION = 1,
|
||||
GPGA_PROT_GET_PASSPHRASE = 2,
|
||||
GPGA_PROT_CLEAR_PASSPHRASE= 3,
|
||||
GPGA_PROT_SHUTDOWN = 4,
|
||||
GPGA_PROT_FLUSH = 5,
|
||||
|
||||
/* Reply codes */
|
||||
GPGA_PROT_REPLY_BASE = 0x10000,
|
||||
GPGA_PROT_OKAY = 0x10001,
|
||||
GPGA_PROT_GOT_PASSPHRASE = 0x10002,
|
||||
|
||||
/* Error codes */
|
||||
GPGA_PROT_ERROR_BASE = 0x20000,
|
||||
GPGA_PROT_PROTOCOL_ERROR = 0x20001,
|
||||
GPGA_PROT_INVALID_REQUEST= 0x20002,
|
||||
GPGA_PROT_CANCELED = 0x20003,
|
||||
GPGA_PROT_NO_PASSPHRASE = 0x20004,
|
||||
GPGA_PROT_BAD_PASSPHRASE = 0x20005,
|
||||
GPGA_PROT_INVALID_DATA = 0x20006,
|
||||
GPGA_PROT_NOT_IMPLEMENTED= 0x20007,
|
||||
GPGA_PROT_UI_PROBLEM = 0x20008
|
||||
};
|
||||
#ifdef ENABLE_AGENT_SUPPORT
|
||||
#include "assuan.h"
|
||||
#endif /*ENABLE_AGENT_SUPPORT*/
|
||||
|
||||
|
||||
#define buftou32( p ) ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \
|
||||
@ -191,187 +168,29 @@ read_passphrase_from_fd( int fd )
|
||||
fd_passwd = pw;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef ENABLE_AGENT_SUPPORT
|
||||
/* Send one option to the gpg-agent. */
|
||||
static int
|
||||
writen (int fd, const void *buf, size_t nbytes)
|
||||
agent_send_option (assuan_context_t ctx, const char *name, const char *value)
|
||||
{
|
||||
#if defined (_WIN32)
|
||||
DWORD nwritten, nleft = nbytes;
|
||||
|
||||
while (nleft > 0)
|
||||
{
|
||||
if (!WriteFile ((HANDLE)write_fd, buf, nleft, &nwritten, NULL))
|
||||
{
|
||||
log_error ("write failed: %s\n", w32_strerror (0));
|
||||
return -1;
|
||||
}
|
||||
/*log_info ("** WriteFile fd=%d nytes=%d nwritten=%d\n",
|
||||
write_fd, nbytes, (int)nwritten);*/
|
||||
Sleep (100);
|
||||
|
||||
nleft -= nwritten;
|
||||
buf = (const BYTE *)buf + nwritten;
|
||||
}
|
||||
#elif defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
|
||||
/* not implemented */
|
||||
#else
|
||||
size_t nleft = nbytes;
|
||||
int nwritten;
|
||||
|
||||
while (nleft > 0)
|
||||
{
|
||||
nwritten = write (fd, buf, nleft);
|
||||
if (nwritten < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
nwritten = 0;
|
||||
else
|
||||
{
|
||||
log_error ("write() failed: %s\n", strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
nleft -= nwritten;
|
||||
buf = (const char*)buf + nwritten;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
readn (int fd, void *buf, size_t buflen, size_t *ret_nread)
|
||||
{
|
||||
#if defined (_WIN32)
|
||||
DWORD nread, nleft = buflen;
|
||||
|
||||
while (nleft > 0)
|
||||
{
|
||||
if (!ReadFile ((HANDLE)read_fd, buf, nleft, &nread, NULL))
|
||||
{
|
||||
log_error ("read() error: %s\n", w32_strerror (0));
|
||||
return -1;
|
||||
}
|
||||
if (!nread || GetLastError() == ERROR_BROKEN_PIPE)
|
||||
break;
|
||||
/*log_info ("** ReadFile fd=%d buflen=%d nread=%d\n",
|
||||
read_fd, buflen, (int)nread);*/
|
||||
Sleep (100);
|
||||
|
||||
nleft -= nread;
|
||||
buf = (BYTE *)buf + nread;
|
||||
}
|
||||
if (ret_nread)
|
||||
*ret_nread = buflen - nleft;
|
||||
|
||||
#elif defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
|
||||
/* not implemented */
|
||||
#else
|
||||
size_t nleft = buflen;
|
||||
int nread;
|
||||
char *p;
|
||||
|
||||
p = buf;
|
||||
while( nleft > 0 )
|
||||
{
|
||||
nread = read ( fd, buf, nleft );
|
||||
if( nread < 0 )
|
||||
{
|
||||
if (errno == EINTR)
|
||||
nread = 0;
|
||||
else
|
||||
{
|
||||
log_error ( "read() error: %s\n", strerror (errno) );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (!nread)
|
||||
break; /* EOF */
|
||||
nleft -= nread;
|
||||
buf = (char*)buf + nread;
|
||||
}
|
||||
if (ret_nread)
|
||||
*ret_nread = buflen - nleft;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read an entire line */
|
||||
static int
|
||||
readaline (int fd, char *buf, size_t buflen)
|
||||
{
|
||||
size_t nleft = buflen;
|
||||
char *p;
|
||||
int nread = 0;
|
||||
|
||||
while (nleft > 0)
|
||||
{
|
||||
int n = read (fd, buf, nleft);
|
||||
if (n < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return -1; /* read error */
|
||||
}
|
||||
else if (!n)
|
||||
{
|
||||
return -1; /* incomplete line */
|
||||
}
|
||||
p = buf;
|
||||
nleft -= n;
|
||||
buf += n;
|
||||
nread += n;
|
||||
|
||||
for (; n && *p != '\n'; n--, p++)
|
||||
;
|
||||
if (n)
|
||||
{
|
||||
break; /* at least one full line available - that's enough.
|
||||
This function is just a temporary hack until we use
|
||||
the assuna lib in gpg. So it is okay to forget
|
||||
about pending bytes */
|
||||
}
|
||||
}
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if !defined (__riscos__)
|
||||
|
||||
#if !defined (_WIN32)
|
||||
/* For the new Assuan protocol we may have to send options */
|
||||
static int
|
||||
agent_send_option (int fd, const char *name, const char *value)
|
||||
{
|
||||
char buf[200];
|
||||
int nread;
|
||||
char *line;
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
line = m_alloc (7 + strlen (name) + 1 + strlen (value) + 2);
|
||||
strcpy (stpcpy (stpcpy (stpcpy (
|
||||
stpcpy (line, "OPTION "), name), "="), value), "\n");
|
||||
i = writen (fd, line, strlen (line));
|
||||
m_free (line);
|
||||
if (i)
|
||||
return -1;
|
||||
|
||||
/* get response */
|
||||
nread = readaline (fd, buf, DIM(buf)-1);
|
||||
if (nread < 3)
|
||||
return -1;
|
||||
|
||||
if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n'))
|
||||
return 0; /* okay */
|
||||
if (!value || !*value)
|
||||
return 0; /* Avoid sending empty option values. */
|
||||
|
||||
return -1;
|
||||
line = xmalloc (7 + strlen (name) + 1 + strlen (value) + 1);
|
||||
strcpy (stpcpy (stpcpy (stpcpy (line, "OPTION "), name), "="), value);
|
||||
rc = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
xfree (line);
|
||||
return rc? -1 : 0;
|
||||
}
|
||||
|
||||
/* Send all required options to the gpg-agent. */
|
||||
static int
|
||||
agent_send_all_options (int fd)
|
||||
agent_send_all_options (assuan_context_t ctx)
|
||||
{
|
||||
char *dft_display = NULL;
|
||||
const char *dft_ttyname = NULL;
|
||||
@ -383,7 +202,7 @@ agent_send_all_options (int fd)
|
||||
dft_display = getenv ("DISPLAY");
|
||||
if (opt.display || dft_display)
|
||||
{
|
||||
if (agent_send_option (fd, "display",
|
||||
if (agent_send_option (ctx, "display",
|
||||
opt.display ? opt.display : dft_display))
|
||||
return -1;
|
||||
}
|
||||
@ -400,7 +219,7 @@ agent_send_all_options (int fd)
|
||||
}
|
||||
if (opt.ttyname || dft_ttyname)
|
||||
{
|
||||
if (agent_send_option (fd, "ttyname",
|
||||
if (agent_send_option (ctx, "ttyname",
|
||||
opt.ttyname ? opt.ttyname : dft_ttyname))
|
||||
return -1;
|
||||
}
|
||||
@ -408,7 +227,7 @@ agent_send_all_options (int fd)
|
||||
dft_ttytype = getenv ("TERM");
|
||||
if (opt.ttytype || (dft_ttyname && dft_ttytype))
|
||||
{
|
||||
if (agent_send_option (fd, "ttytype",
|
||||
if (agent_send_option (ctx, "ttytype",
|
||||
opt.ttyname ? opt.ttytype : dft_ttytype))
|
||||
return -1;
|
||||
}
|
||||
@ -421,7 +240,7 @@ agent_send_all_options (int fd)
|
||||
#endif
|
||||
if (opt.lc_ctype || (dft_ttyname && dft_lc))
|
||||
{
|
||||
rc = agent_send_option (fd, "lc-ctype",
|
||||
rc = agent_send_option (ctx, "lc-ctype",
|
||||
opt.lc_ctype ? opt.lc_ctype : dft_lc);
|
||||
}
|
||||
#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
|
||||
@ -442,7 +261,7 @@ agent_send_all_options (int fd)
|
||||
#endif
|
||||
if (opt.lc_messages || (dft_ttyname && dft_lc))
|
||||
{
|
||||
rc = agent_send_option (fd, "lc-messages",
|
||||
rc = agent_send_option (ctx, "lc-messages",
|
||||
opt.lc_messages ? opt.lc_messages : dft_lc);
|
||||
}
|
||||
#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
|
||||
@ -454,170 +273,147 @@ agent_send_all_options (int fd)
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
#endif /*!_WIN32*/
|
||||
#endif /*ENABLE_AGENT_SUPPORT*/
|
||||
|
||||
|
||||
/*
|
||||
* Open a connection to the agent and send the magic string
|
||||
* Returns: -1 on error or an filedescriptor for urther processing
|
||||
* Open a connection to the agent and initializes the connection.
|
||||
* Returns: -1 on error; on success a file descriptor for that
|
||||
* connection is returned.
|
||||
*/
|
||||
|
||||
static int
|
||||
agent_open (int *ret_prot)
|
||||
#ifdef ENABLE_AGENT_SUPPORT
|
||||
static assuan_context_t
|
||||
agent_open (void)
|
||||
{
|
||||
#if defined (_WIN32)
|
||||
int fd;
|
||||
char *infostr, *p;
|
||||
HANDLE h;
|
||||
char pidstr[128];
|
||||
int rc;
|
||||
assuan_context_t ctx;
|
||||
char *infostr, *p;
|
||||
int prot;
|
||||
int pid;
|
||||
|
||||
*ret_prot = 0;
|
||||
if ( !(infostr = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG",
|
||||
"agentPID"))
|
||||
|| *infostr == '0') {
|
||||
log_error( _("gpg-agent is not available in this session\n"));
|
||||
return -1;
|
||||
}
|
||||
free(infostr);
|
||||
|
||||
sprintf(pidstr, "%u", (unsigned int)GetCurrentProcessId());
|
||||
if (write_w32_registry_string(NULL, "Software\\GNU\\GnuPG",
|
||||
"agentCID", pidstr)) {
|
||||
log_error( _("can't set client pid for the agent\n") );
|
||||
return -1;
|
||||
}
|
||||
h = OpenEvent(EVENT_ALL_ACCESS, FALSE, "gpg_agent");
|
||||
SetEvent(h);
|
||||
Sleep(50); /* some time for the server */
|
||||
if ( !(p = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG",
|
||||
"agentReadFD")) ) {
|
||||
log_error( _("can't get server read FD for the agent\n") );
|
||||
return -1;
|
||||
}
|
||||
read_fd = atol(p);
|
||||
free(p);
|
||||
if ( !(p = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG",
|
||||
"agentWriteFD")) ) {
|
||||
log_error ( _("can't get server write FD for the agent\n") );
|
||||
return -1;
|
||||
}
|
||||
write_fd = atol(p);
|
||||
free(p);
|
||||
fd = 0;
|
||||
|
||||
if ( writen ( fd, "GPGA\0\0\0\x01", 8 ) ) {
|
||||
fd = -1;
|
||||
}
|
||||
#else /* Posix */
|
||||
|
||||
int fd;
|
||||
char *infostr, *p;
|
||||
struct sockaddr_un client_addr;
|
||||
size_t len;
|
||||
int prot;
|
||||
|
||||
if (opt.gpg_agent_info)
|
||||
infostr = m_strdup (opt.gpg_agent_info);
|
||||
else
|
||||
{
|
||||
infostr = getenv ( "GPG_AGENT_INFO" );
|
||||
if ( !infostr ) {
|
||||
if (opt.gpg_agent_info)
|
||||
infostr = xstrdup (opt.gpg_agent_info);
|
||||
else
|
||||
{
|
||||
infostr = getenv ( "GPG_AGENT_INFO" );
|
||||
if (!infostr || !*infostr)
|
||||
{
|
||||
log_error (_("gpg-agent is not available in this session\n"));
|
||||
opt.use_agent = 0;
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
infostr = m_strdup ( infostr );
|
||||
}
|
||||
infostr = xstrdup ( infostr );
|
||||
}
|
||||
|
||||
if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
|
||||
{
|
||||
log_error ( _("malformed GPG_AGENT_INFO environment variable\n"));
|
||||
xfree (infostr);
|
||||
opt.use_agent = 0;
|
||||
return NULL;
|
||||
}
|
||||
*p++ = 0;
|
||||
pid = atoi (p);
|
||||
while (*p && *p != PATHSEP_C)
|
||||
p++;
|
||||
prot = *p? atoi (p+1) : 0;
|
||||
if (prot != 1)
|
||||
{
|
||||
log_error (_("gpg-agent protocol version %d is not supported\n"), prot);
|
||||
xfree (infostr);
|
||||
opt.use_agent = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = assuan_socket_connect (&ctx, infostr, pid);
|
||||
if (rc)
|
||||
{
|
||||
log_error ( _("can't connect to `%s': %s\n"),
|
||||
infostr, assuan_strerror (rc));
|
||||
xfree (infostr );
|
||||
opt.use_agent = 0;
|
||||
return NULL;
|
||||
}
|
||||
xfree (infostr);
|
||||
|
||||
if ( !(p = strchr ( infostr, ':')) || p == infostr
|
||||
|| (p-infostr)+1 >= sizeof client_addr.sun_path ) {
|
||||
log_error( _("malformed GPG_AGENT_INFO environment variable\n"));
|
||||
m_free (infostr );
|
||||
opt.use_agent = 0;
|
||||
return -1;
|
||||
if (agent_send_all_options (ctx))
|
||||
{
|
||||
log_error (_("problem with the agent - disabling agent use\n"));
|
||||
assuan_disconnect (ctx);
|
||||
opt.use_agent = 0;
|
||||
return NULL;
|
||||
}
|
||||
*p++ = 0;
|
||||
/* See whether this is the new gpg-agent using the Assuna protocl.
|
||||
This agent identifies itself by have an info string with a
|
||||
version number in the 3rd field. */
|
||||
while (*p && *p != ':')
|
||||
p++;
|
||||
prot = *p? atoi (p+1) : 0;
|
||||
if ( prot < 0 || prot > 1) {
|
||||
log_error (_("gpg-agent protocol version %d is not supported\n"),prot);
|
||||
m_free (infostr );
|
||||
opt.use_agent = 0;
|
||||
return -1;
|
||||
}
|
||||
*ret_prot = prot;
|
||||
|
||||
if( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ) {
|
||||
log_error ("can't create socket: %s\n", strerror(errno) );
|
||||
m_free (infostr );
|
||||
opt.use_agent = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset( &client_addr, 0, sizeof client_addr );
|
||||
client_addr.sun_family = AF_UNIX;
|
||||
strcpy( client_addr.sun_path, infostr );
|
||||
len = offsetof (struct sockaddr_un, sun_path)
|
||||
+ strlen(client_addr.sun_path) + 1;
|
||||
|
||||
if( connect( fd, (struct sockaddr*)&client_addr, len ) == -1 ) {
|
||||
log_error ( _("can't connect to `%s': %s\n"),
|
||||
infostr, strerror (errno) );
|
||||
m_free (infostr );
|
||||
close (fd );
|
||||
opt.use_agent = 0;
|
||||
return -1;
|
||||
}
|
||||
m_free (infostr);
|
||||
|
||||
if (!prot) {
|
||||
if ( writen ( fd, "GPGA\0\0\0\x01", 8 ) ) {
|
||||
close (fd);
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
else { /* assuan based gpg-agent */
|
||||
char line[200];
|
||||
int nread;
|
||||
|
||||
nread = readaline (fd, line, DIM(line));
|
||||
if (nread < 3 || !(line[0] == 'O' && line[1] == 'K'
|
||||
&& (line[2] == '\n' || line[2] == ' ')) ) {
|
||||
log_error ( _("communication problem with gpg-agent\n"));
|
||||
close (fd );
|
||||
opt.use_agent = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (agent_send_all_options (fd)) {
|
||||
log_error (_("problem with the agent - disabling agent use\n"));
|
||||
close (fd);
|
||||
opt.use_agent = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
return fd;
|
||||
return ctx;
|
||||
}
|
||||
#endif/*ENABLE_AGENT_SUPPORT*/
|
||||
|
||||
|
||||
#ifdef ENABLE_AGENT_SUPPORT
|
||||
static void
|
||||
agent_close ( int fd )
|
||||
agent_close (assuan_context_t ctx)
|
||||
{
|
||||
#if defined (_WIN32)
|
||||
HANDLE h = OpenEvent(EVENT_ALL_ACCESS, FALSE, "gpg_agent");
|
||||
ResetEvent(h);
|
||||
#else
|
||||
close (fd);
|
||||
#endif
|
||||
assuan_disconnect (ctx);
|
||||
}
|
||||
#endif /* !__riscos__ */
|
||||
#endif /*ENABLE_AGENT_SUPPORT*/
|
||||
|
||||
|
||||
/* Copy the text ATEXT into the buffer P and do plus '+' and percent
|
||||
escaping. Note that the provided buffer needs to be 3 times the
|
||||
size of ATEXT plus 1. Returns a pointer to the leading Nul in P. */
|
||||
#ifdef ENABLE_AGENT_SUPPORT
|
||||
static char *
|
||||
percent_plus_escape (char *p, const char *atext)
|
||||
{
|
||||
const unsigned char *s;
|
||||
|
||||
for (s=atext; *s; s++)
|
||||
{
|
||||
if (*s < ' ' || *s == '+')
|
||||
{
|
||||
sprintf (p, "%%%02X", *s);
|
||||
p += 3;
|
||||
}
|
||||
else if (*s == ' ')
|
||||
*p++ = '+';
|
||||
else
|
||||
*p++ = *s;
|
||||
}
|
||||
*p = 0;
|
||||
return p;
|
||||
}
|
||||
#endif /*ENABLE_AGENT_SUPPORT*/
|
||||
|
||||
|
||||
#ifdef ENABLE_AGENT_SUPPORT
|
||||
|
||||
/* Object for the agent_okay_cb function. */
|
||||
struct agent_okay_cb_s {
|
||||
char *pw;
|
||||
};
|
||||
|
||||
/* A callback used to get the passphrase from the okay line. See
|
||||
agent-get_passphrase for details. LINE is the rest of the OK
|
||||
status line without leading white spaces. */
|
||||
static assuan_error_t
|
||||
agent_okay_cb (void *opaque, const char *line)
|
||||
{
|
||||
struct agent_okay_cb_s *parm = opaque;
|
||||
int i;
|
||||
|
||||
/* Note: If the malloc below fails we won't be able to wipe the
|
||||
memory at LINE given the current implementation of the Assuan
|
||||
code. There is no easy ay around this w/o adding a lot of more
|
||||
memory function code to allow wiping arbitrary stuff on memory
|
||||
failure. */
|
||||
parm->pw = xmalloc_secure (strlen (line)/2+2);
|
||||
|
||||
for (i=0; hexdigitp (line) && hexdigitp (line+1); line += 2)
|
||||
parm->pw[i++] = xtoi_2 (line);
|
||||
parm->pw[i] = 0;
|
||||
return 0;
|
||||
}
|
||||
#endif /*ENABLE_AGENT_SUPPORT*/
|
||||
|
||||
|
||||
|
||||
@ -636,19 +432,13 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
|
||||
const char *custom_description,
|
||||
const char *custom_prompt, int *canceled)
|
||||
{
|
||||
#if defined(__riscos__)
|
||||
return NULL;
|
||||
#else
|
||||
size_t n;
|
||||
#ifdef ENABLE_AGENT_SUPPORT
|
||||
char *atext = NULL;
|
||||
char buf[50];
|
||||
int fd = -1;
|
||||
u32 reply;
|
||||
assuan_context_t ctx = NULL;
|
||||
char *pw = NULL;
|
||||
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
|
||||
byte fpr[MAX_FINGERPRINT_LEN];
|
||||
int have_fpr = 0;
|
||||
int prot;
|
||||
char *orig_codeset = NULL;
|
||||
|
||||
if (canceled)
|
||||
@ -667,7 +457,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
|
||||
}
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
/* The Assuan agent protol requires us to transmit utf-8 strings */
|
||||
/* The Assuan agent protocol requires us to transmit utf-8 strings */
|
||||
orig_codeset = bind_textdomain_codeset (PACKAGE, NULL);
|
||||
#ifdef HAVE_LANGINFO_CODESET
|
||||
if (!orig_codeset)
|
||||
@ -681,7 +471,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( (fd = agent_open (&prot)) == -1 )
|
||||
if ( !(ctx = agent_open ()) )
|
||||
goto failure;
|
||||
|
||||
if (custom_description)
|
||||
@ -740,100 +530,23 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
|
||||
else
|
||||
atext = m_strdup ( _("Enter passphrase\n") );
|
||||
|
||||
if (!prot)
|
||||
{ /* old style protocol */
|
||||
size_t nread;
|
||||
|
||||
n = 4 + 20 + strlen (atext);
|
||||
u32tobuf (buf, n );
|
||||
u32tobuf (buf+4, GPGA_PROT_GET_PASSPHRASE );
|
||||
memcpy (buf+8, fpr, 20 );
|
||||
if ( writen ( fd, buf, 28 ) || writen ( fd, atext, strlen (atext) ) )
|
||||
goto failure;
|
||||
m_free (atext); atext = NULL;
|
||||
|
||||
/* get response */
|
||||
if ( readn ( fd, buf, 12, &nread ) )
|
||||
goto failure;
|
||||
|
||||
if ( nread < 8 )
|
||||
{
|
||||
log_error ( "response from agent too short\n" );
|
||||
goto failure;
|
||||
}
|
||||
n = buftou32 ( buf );
|
||||
reply = buftou32 ( buf + 4 );
|
||||
if ( reply == GPGA_PROT_GOT_PASSPHRASE )
|
||||
{
|
||||
size_t pwlen;
|
||||
size_t nn;
|
||||
|
||||
if ( nread < 12 || n < 8 )
|
||||
{
|
||||
log_error ( "response from agent too short\n" );
|
||||
goto failure;
|
||||
}
|
||||
pwlen = buftou32 ( buf + 8 );
|
||||
nread -= 12;
|
||||
n -= 8;
|
||||
if ( pwlen > n || n > 1000 )
|
||||
{
|
||||
log_error (_("passphrase too long\n"));
|
||||
/* or protocol error */
|
||||
goto failure;
|
||||
}
|
||||
/* we read the whole block in one chunk to give no hints
|
||||
* on how long the passhrase actually is - this wastes some bytes
|
||||
* but because we already have this padding we should not loosen
|
||||
* this by issuing 2 read calls */
|
||||
pw = m_alloc_secure ( n+1 );
|
||||
if ( readn ( fd, pw, n, &nn ) )
|
||||
goto failure;
|
||||
if ( n != nn )
|
||||
{
|
||||
log_error (_("invalid response from agent\n"));
|
||||
goto failure;
|
||||
}
|
||||
pw[pwlen] = 0; /* make a C String */
|
||||
agent_close (fd);
|
||||
if (pk)
|
||||
free_public_key( pk );
|
||||
#ifdef ENABLE_NLS
|
||||
if (orig_codeset)
|
||||
bind_textdomain_codeset (PACKAGE, orig_codeset);
|
||||
#endif
|
||||
m_free (orig_codeset);
|
||||
return pw;
|
||||
}
|
||||
else if ( reply == GPGA_PROT_CANCELED )
|
||||
{
|
||||
log_info ( _("cancelled by user\n") );
|
||||
if (canceled)
|
||||
*canceled = 1;
|
||||
}
|
||||
else
|
||||
log_error ( _("problem with the agent: agent returns 0x%lx\n"),
|
||||
(ulong)reply );
|
||||
}
|
||||
else
|
||||
{ /* The new Assuan protocol */
|
||||
int nread;
|
||||
{
|
||||
char *line, *p;
|
||||
const unsigned char *s;
|
||||
int i;
|
||||
int i, rc;
|
||||
struct agent_okay_cb_s okay_cb_parm;
|
||||
|
||||
if (!tryagain_text)
|
||||
tryagain_text = "X";
|
||||
else
|
||||
tryagain_text = _(tryagain_text);
|
||||
|
||||
/* We allocate 2 time the needed space for atext so that there
|
||||
is enough space for escaping */
|
||||
line = m_alloc (15 + 46
|
||||
+ 3*strlen (tryagain_text)
|
||||
/* We allocate 23 times the needed space for thye texts so that
|
||||
there is enough space for escaping. */
|
||||
line = xmalloc (15 + 46
|
||||
+ 3*strlen (atext)
|
||||
+ 3*strlen (custom_prompt? custom_prompt:"")
|
||||
+ 2);
|
||||
+ 3*strlen (tryagain_text)
|
||||
+ 1);
|
||||
strcpy (line, "GET_PASSPHRASE ");
|
||||
p = line+15;
|
||||
if (!mode && have_fpr)
|
||||
@ -842,92 +555,50 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
|
||||
sprintf (p, "%02X", fpr[i]);
|
||||
}
|
||||
else
|
||||
*p++ = 'X'; /* no caching */
|
||||
*p++ = 'X'; /* No caching. */
|
||||
*p++ = ' ';
|
||||
for (i=0, s=tryagain_text; *s; s++)
|
||||
{
|
||||
if (*s < ' ' || *s == '+')
|
||||
{
|
||||
sprintf (p, "%%%02X", *s);
|
||||
p += 3;
|
||||
}
|
||||
else if (*s == ' ')
|
||||
*p++ = '+';
|
||||
else
|
||||
*p++ = *s;
|
||||
}
|
||||
|
||||
p = percent_plus_escape (p, tryagain_text);
|
||||
*p++ = ' ';
|
||||
|
||||
/* The prompt. */
|
||||
if (custom_prompt)
|
||||
{
|
||||
char *tmp = native_to_utf8 (custom_prompt);
|
||||
for (i=0, s=tmp; *s; s++)
|
||||
{
|
||||
if (*s < ' ' || *s == '+')
|
||||
{
|
||||
sprintf (p, "%%%02X", *s);
|
||||
p += 3;
|
||||
}
|
||||
else if (*s == ' ')
|
||||
*p++ = '+';
|
||||
else
|
||||
*p++ = *s;
|
||||
}
|
||||
p = percent_plus_escape (p, tmp);
|
||||
xfree (tmp);
|
||||
}
|
||||
else
|
||||
*p++ = 'X'; /* Use the standard prompt */
|
||||
|
||||
*p++ = 'X'; /* Use the standard prompt. */
|
||||
*p++ = ' ';
|
||||
/* copy description */
|
||||
for (i=0, s= atext; *s; s++)
|
||||
{
|
||||
if (*s < ' ' || *s == '+')
|
||||
{
|
||||
sprintf (p, "%%%02X", *s);
|
||||
p += 3;
|
||||
}
|
||||
else if (*s == ' ')
|
||||
*p++ = '+';
|
||||
else
|
||||
*p++ = *s;
|
||||
}
|
||||
*p++ = '\n';
|
||||
i = writen (fd, line, p - line);
|
||||
m_free (line);
|
||||
if (i)
|
||||
goto failure;
|
||||
m_free (atext); atext = NULL;
|
||||
|
||||
/* get response */
|
||||
pw = m_alloc_secure (500);
|
||||
nread = readaline (fd, pw, 499);
|
||||
if (nread < 3)
|
||||
goto failure;
|
||||
|
||||
if (pw[0] == 'O' && pw[1] == 'K' && pw[2] == ' ')
|
||||
{ /* we got a passphrase - convert it back from hex */
|
||||
size_t pwlen = 0;
|
||||
|
||||
for (i=3; i < nread && hexdigitp (pw+i); i+=2)
|
||||
pw[pwlen++] = xtoi_2 (pw+i);
|
||||
pw[pwlen] = 0; /* make a C String */
|
||||
agent_close (fd);
|
||||
/* Copy description. */
|
||||
percent_plus_escape (p, atext);
|
||||
|
||||
/* Call gpg-agent. */
|
||||
memset (&okay_cb_parm, 0, sizeof okay_cb_parm);
|
||||
rc = assuan_transact2 (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
agent_okay_cb, &okay_cb_parm);
|
||||
|
||||
xfree (line);
|
||||
xfree (atext); atext = NULL;
|
||||
if (!rc)
|
||||
{
|
||||
assert (okay_cb_parm.pw);
|
||||
pw = okay_cb_parm.pw;
|
||||
agent_close (ctx);
|
||||
if (pk)
|
||||
free_public_key( pk );
|
||||
#ifdef ENABLE_NLS
|
||||
if (orig_codeset)
|
||||
bind_textdomain_codeset (PACKAGE, orig_codeset);
|
||||
#endif
|
||||
m_free (orig_codeset);
|
||||
xfree (orig_codeset);
|
||||
return pw;
|
||||
}
|
||||
else if (nread > 4 && !memcmp (pw, "ERR ", 4)
|
||||
&& (0xffff & strtoul (&pw[4], NULL, 0)) == 99)
|
||||
else if (rc && (rc & 0xffff) == 99)
|
||||
{
|
||||
/* 99 is GPG_ERR_CANCELED. FIXME: Check tail and overflow,
|
||||
and use gpg-error. */
|
||||
/* 99 is GPG_ERR_CANCELED. */
|
||||
log_info (_("cancelled by user\n") );
|
||||
if (canceled)
|
||||
*canceled = 1;
|
||||
@ -937,7 +608,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
|
||||
log_error (_("problem with the agent - disabling agent use\n"));
|
||||
opt.use_agent = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
failure:
|
||||
@ -945,34 +616,28 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
|
||||
if (orig_codeset)
|
||||
bind_textdomain_codeset (PACKAGE, orig_codeset);
|
||||
#endif
|
||||
m_free (atext);
|
||||
if ( fd != -1 )
|
||||
agent_close (fd);
|
||||
m_free (pw );
|
||||
xfree (atext);
|
||||
agent_close (ctx);
|
||||
xfree (pw );
|
||||
if (pk)
|
||||
free_public_key( pk );
|
||||
|
||||
|
||||
#endif /*ENABLE_AGENT_SUPPORT*/
|
||||
|
||||
return NULL;
|
||||
#endif /* Posix or W32 */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Clear the cached passphrase
|
||||
*/
|
||||
void
|
||||
passphrase_clear_cache ( u32 *keyid, int algo )
|
||||
{
|
||||
#if defined(__riscos__)
|
||||
return ;
|
||||
#else
|
||||
size_t n;
|
||||
char buf[200];
|
||||
int fd = -1;
|
||||
size_t nread;
|
||||
u32 reply;
|
||||
#ifdef ENABLE_AGENT_SUPPORT
|
||||
assuan_context_t ctx = NULL;
|
||||
PKT_public_key *pk;
|
||||
byte fpr[MAX_FINGERPRINT_LEN];
|
||||
int prot;
|
||||
|
||||
#if MAX_FINGERPRINT_LEN < 20
|
||||
#error agent needs a 20 byte fingerprint
|
||||
@ -981,7 +646,7 @@ passphrase_clear_cache ( u32 *keyid, int algo )
|
||||
if (!opt.use_agent)
|
||||
return;
|
||||
|
||||
pk = m_alloc_clear ( sizeof *pk );
|
||||
pk = xcalloc (1, sizeof *pk);
|
||||
memset (fpr, 0, MAX_FINGERPRINT_LEN );
|
||||
if( !keyid || get_pubkey( pk, keyid ) )
|
||||
{
|
||||
@ -993,58 +658,23 @@ passphrase_clear_cache ( u32 *keyid, int algo )
|
||||
fingerprint_from_pk( pk, fpr, &dummy );
|
||||
}
|
||||
|
||||
if ( (fd = agent_open (&prot)) == -1 )
|
||||
if ( !(ctx = agent_open ()) )
|
||||
goto failure;
|
||||
|
||||
if (!prot)
|
||||
{
|
||||
n = 4 + 20;
|
||||
u32tobuf (buf, n );
|
||||
u32tobuf (buf+4, GPGA_PROT_CLEAR_PASSPHRASE );
|
||||
memcpy (buf+8, fpr, 20 );
|
||||
if ( writen ( fd, buf, 28 ) )
|
||||
goto failure;
|
||||
|
||||
/* get response */
|
||||
if ( readn ( fd, buf, 8, &nread ) )
|
||||
goto failure;
|
||||
|
||||
if ( nread < 8 ) {
|
||||
log_error ( "response from agent too short\n" );
|
||||
goto failure;
|
||||
}
|
||||
|
||||
reply = buftou32 ( buf + 4 );
|
||||
if ( reply != GPGA_PROT_OKAY && reply != GPGA_PROT_NO_PASSPHRASE )
|
||||
{
|
||||
log_error ( _("problem with the agent: agent returns 0x%lx\n"),
|
||||
(ulong)reply );
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* The assuan protocol */
|
||||
{
|
||||
char *line, *p;
|
||||
int i;
|
||||
int i, rc;
|
||||
|
||||
line = m_alloc (17 + 40 + 2);
|
||||
line = xmalloc (17 + 40 + 2);
|
||||
strcpy (line, "CLEAR_PASSPHRASE ");
|
||||
p = line+17;
|
||||
for (i=0; i < 20; i++, p +=2 )
|
||||
sprintf (p, "%02X", fpr[i]);
|
||||
*p++ = '\n';
|
||||
i = writen (fd, line, p - line);
|
||||
m_free (line);
|
||||
if (i)
|
||||
goto failure;
|
||||
|
||||
/* get response */
|
||||
nread = readaline (fd, buf, DIM(buf)-1);
|
||||
if (nread < 3)
|
||||
goto failure;
|
||||
|
||||
if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n'))
|
||||
;
|
||||
else
|
||||
*p = 0;
|
||||
|
||||
rc = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
xfree (line);
|
||||
if (rc)
|
||||
{
|
||||
log_error (_("problem with the agent - disabling agent use\n"));
|
||||
opt.use_agent = 0;
|
||||
@ -1052,11 +682,10 @@ passphrase_clear_cache ( u32 *keyid, int algo )
|
||||
}
|
||||
|
||||
failure:
|
||||
if (fd != -1)
|
||||
agent_close (fd);
|
||||
agent_close (ctx);
|
||||
if (pk)
|
||||
free_public_key( pk );
|
||||
#endif /* Posix or W32 */
|
||||
#endif /*ENABLE_AGENT_SUPPORT*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,3 +1,11 @@
|
||||
2005-04-04 Werner Koch <wk@g10code.com>
|
||||
|
||||
* memory.h (xcalloc, xcalloc_secure): Replaced macros by functions.
|
||||
|
||||
2005-03-31 Werner Koch <wk@g10code.com>
|
||||
|
||||
* assuan.h: New. Taken from libassuan 0.6.9.
|
||||
|
||||
2005-03-18 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* ttyio.h: Prototype tty_enable_completion(), and
|
||||
@ -506,7 +514,7 @@ Tue Mar 3 15:11:21 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
|
||||
Copyright 1998, 1999, 2000, 2001, 2002, 2003,
|
||||
2004 Free Software Foundation, Inc.
|
||||
2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is free software; as a special exception the author gives
|
||||
unlimited permission to copy and/or distribute it, with or without
|
||||
|
261
include/assuan.h
Normal file
261
include/assuan.h
Normal file
@ -0,0 +1,261 @@
|
||||
/* assuan.c - Definitions for the Assuan protocol
|
||||
* 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. For the standalone version
|
||||
of gnupg we only need the ability to connect to a server, so we
|
||||
dropped everything else and maintain this separate copy. */
|
||||
|
||||
#ifndef ASSUAN_H
|
||||
#define ASSUAN_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ASSUAN_No_Error = 0,
|
||||
ASSUAN_General_Error = 1,
|
||||
ASSUAN_Out_Of_Core = 2,
|
||||
ASSUAN_Invalid_Value = 3,
|
||||
ASSUAN_Timeout = 4,
|
||||
ASSUAN_Read_Error = 5,
|
||||
ASSUAN_Write_Error = 6,
|
||||
ASSUAN_Problem_Starting_Server = 7,
|
||||
ASSUAN_Not_A_Server = 8,
|
||||
ASSUAN_Not_A_Client = 9,
|
||||
ASSUAN_Nested_Commands = 10,
|
||||
ASSUAN_Invalid_Response = 11,
|
||||
ASSUAN_No_Data_Callback = 12,
|
||||
ASSUAN_No_Inquire_Callback = 13,
|
||||
ASSUAN_Connect_Failed = 14,
|
||||
ASSUAN_Accept_Failed = 15,
|
||||
|
||||
/* Error codes above 99 are meant as status codes */
|
||||
ASSUAN_Not_Implemented = 100,
|
||||
ASSUAN_Server_Fault = 101,
|
||||
ASSUAN_Invalid_Command = 102,
|
||||
ASSUAN_Unknown_Command = 103,
|
||||
ASSUAN_Syntax_Error = 104,
|
||||
ASSUAN_Parameter_Error = 105,
|
||||
ASSUAN_Parameter_Conflict = 106,
|
||||
ASSUAN_Line_Too_Long = 107,
|
||||
ASSUAN_Line_Not_Terminated = 108,
|
||||
ASSUAN_No_Input = 109,
|
||||
ASSUAN_No_Output = 110,
|
||||
ASSUAN_Canceled = 111,
|
||||
ASSUAN_Unsupported_Algorithm = 112,
|
||||
ASSUAN_Server_Resource_Problem = 113,
|
||||
ASSUAN_Server_IO_Error = 114,
|
||||
ASSUAN_Server_Bug = 115,
|
||||
ASSUAN_No_Data_Available = 116,
|
||||
ASSUAN_Invalid_Data = 117,
|
||||
ASSUAN_Unexpected_Command = 118,
|
||||
ASSUAN_Too_Much_Data = 119,
|
||||
ASSUAN_Inquire_Unknown = 120,
|
||||
ASSUAN_Inquire_Error = 121,
|
||||
ASSUAN_Invalid_Option = 122,
|
||||
ASSUAN_Invalid_Index = 123,
|
||||
ASSUAN_Unexpected_Status = 124,
|
||||
ASSUAN_Unexpected_Data = 125,
|
||||
ASSUAN_Invalid_Status = 126,
|
||||
ASSUAN_Locale_Problem = 127,
|
||||
ASSUAN_Not_Confirmed = 128,
|
||||
|
||||
/* Error codes in the range 1000 to 9999 may be used by applications
|
||||
at their own discretion. */
|
||||
ASSUAN_USER_ERROR_FIRST = 1000,
|
||||
ASSUAN_USER_ERROR_LAST = 9999
|
||||
|
||||
} assuan_error_t;
|
||||
|
||||
|
||||
#define ASSUAN_LINELENGTH 1002 /* 1000 + [CR,]LF */
|
||||
|
||||
struct assuan_context_s;
|
||||
typedef struct assuan_context_s *assuan_context_t;
|
||||
|
||||
/*-- assuan-handler.c --*/
|
||||
int assuan_register_command (assuan_context_t ctx,
|
||||
const char *cmd_string,
|
||||
int (*handler)(assuan_context_t, char *));
|
||||
int assuan_register_bye_notify (assuan_context_t ctx,
|
||||
void (*fnc)(assuan_context_t));
|
||||
int assuan_register_reset_notify (assuan_context_t ctx,
|
||||
void (*fnc)(assuan_context_t));
|
||||
int assuan_register_cancel_notify (assuan_context_t ctx,
|
||||
void (*fnc)(assuan_context_t));
|
||||
int assuan_register_input_notify (assuan_context_t ctx,
|
||||
void (*fnc)(assuan_context_t, const char *));
|
||||
int assuan_register_output_notify (assuan_context_t ctx,
|
||||
void (*fnc)(assuan_context_t, const char *));
|
||||
|
||||
int assuan_register_option_handler (assuan_context_t ctx,
|
||||
int (*fnc)(assuan_context_t,
|
||||
const char*, const char*));
|
||||
|
||||
int assuan_process (assuan_context_t ctx);
|
||||
int assuan_process_next (assuan_context_t ctx);
|
||||
int assuan_get_active_fds (assuan_context_t ctx, int what,
|
||||
int *fdarray, int fdarraysize);
|
||||
|
||||
|
||||
FILE *assuan_get_data_fp (assuan_context_t ctx);
|
||||
assuan_error_t assuan_set_okay_line (assuan_context_t ctx, const char *line);
|
||||
assuan_error_t assuan_write_status (assuan_context_t ctx,
|
||||
const char *keyword, const char *text);
|
||||
|
||||
/* Negotiate a file descriptor. If LINE contains "FD=N", returns N
|
||||
assuming a local file descriptor. If LINE contains "FD" reads a
|
||||
file descriptor via CTX and stores it in *RDF (the CTX must be
|
||||
capable of passing file descriptors). */
|
||||
assuan_error_t assuan_command_parse_fd (assuan_context_t ctx, char *line,
|
||||
int *rfd);
|
||||
|
||||
/*-- assuan-listen.c --*/
|
||||
assuan_error_t assuan_set_hello_line (assuan_context_t ctx, const char *line);
|
||||
assuan_error_t assuan_accept (assuan_context_t ctx);
|
||||
int assuan_get_input_fd (assuan_context_t ctx);
|
||||
int assuan_get_output_fd (assuan_context_t ctx);
|
||||
assuan_error_t assuan_close_input_fd (assuan_context_t ctx);
|
||||
assuan_error_t assuan_close_output_fd (assuan_context_t ctx);
|
||||
|
||||
|
||||
/*-- assuan-pipe-server.c --*/
|
||||
int assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2]);
|
||||
void assuan_deinit_server (assuan_context_t ctx);
|
||||
|
||||
/*-- assuan-socket-server.c --*/
|
||||
int assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd);
|
||||
int assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd);
|
||||
|
||||
|
||||
/*-- assuan-pipe-connect.c --*/
|
||||
assuan_error_t assuan_pipe_connect (assuan_context_t *ctx, const char *name,
|
||||
char *const argv[], int *fd_child_list);
|
||||
assuan_error_t assuan_pipe_connect2 (assuan_context_t *ctx, const char *name,
|
||||
char *const argv[], int *fd_child_list,
|
||||
void (*atfork) (void*, int),
|
||||
void *atforkvalue);
|
||||
/*-- assuan-socket-connect.c --*/
|
||||
assuan_error_t assuan_socket_connect (assuan_context_t *ctx, const char *name,
|
||||
pid_t server_pid);
|
||||
|
||||
/*-- assuan-domain-connect.c --*/
|
||||
|
||||
/* Connect to a Unix domain socket server. RENDEZVOUSFD is
|
||||
bidirectional file descriptor (normally returned via socketpair)
|
||||
which the client can use to rendezvous with the server. SERVER s
|
||||
the server's pid. */
|
||||
assuan_error_t assuan_domain_connect (assuan_context_t *r_ctx,
|
||||
int rendezvousfd,
|
||||
pid_t server);
|
||||
|
||||
/*-- assuan-domain-server.c --*/
|
||||
|
||||
/* RENDEZVOUSFD is a bidirectional file descriptor (normally returned
|
||||
via socketpair) that the domain server can use to rendezvous with
|
||||
the client. CLIENT is the client's pid. */
|
||||
assuan_error_t assuan_init_domain_server (assuan_context_t *r_ctx,
|
||||
int rendezvousfd,
|
||||
pid_t client);
|
||||
|
||||
|
||||
/*-- assuan-connect.c --*/
|
||||
void assuan_disconnect (assuan_context_t ctx);
|
||||
pid_t assuan_get_pid (assuan_context_t ctx);
|
||||
|
||||
/*-- assuan-client.c --*/
|
||||
assuan_error_t
|
||||
assuan_transact (assuan_context_t ctx,
|
||||
const char *command,
|
||||
assuan_error_t (*data_cb)(void *, const void *, size_t),
|
||||
void *data_cb_arg,
|
||||
assuan_error_t (*inquire_cb)(void*, const char *),
|
||||
void *inquire_cb_arg,
|
||||
assuan_error_t (*status_cb)(void*, const char *),
|
||||
void *status_cb_arg);
|
||||
assuan_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);
|
||||
|
||||
|
||||
/*-- assuan-inquire.c --*/
|
||||
assuan_error_t assuan_inquire (assuan_context_t ctx, const char *keyword,
|
||||
unsigned char **r_buffer, size_t *r_length,
|
||||
size_t maxlen);
|
||||
|
||||
/*-- assuan-buffer.c --*/
|
||||
assuan_error_t assuan_read_line (assuan_context_t ctx,
|
||||
char **line, size_t *linelen);
|
||||
int assuan_pending_line (assuan_context_t ctx);
|
||||
assuan_error_t assuan_write_line (assuan_context_t ctx, const char *line );
|
||||
assuan_error_t assuan_send_data (assuan_context_t ctx,
|
||||
const void *buffer, size_t length);
|
||||
|
||||
/*-- assuan-util.c --*/
|
||||
void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
|
||||
void *(*new_realloc_func)(void *p, size_t n),
|
||||
void (*new_free_func)(void*) );
|
||||
void assuan_set_log_stream (assuan_context_t ctx, FILE *fp);
|
||||
int assuan_set_error (assuan_context_t ctx, int err, const char *text);
|
||||
void assuan_set_pointer (assuan_context_t ctx, void *pointer);
|
||||
void *assuan_get_pointer (assuan_context_t ctx);
|
||||
|
||||
void assuan_begin_confidential (assuan_context_t ctx);
|
||||
void assuan_end_confidential (assuan_context_t ctx);
|
||||
|
||||
/*-- assuan-errors.c (built) --*/
|
||||
const char *assuan_strerror (assuan_error_t err);
|
||||
|
||||
/*-- assuan-logging.c --*/
|
||||
|
||||
/* Set the stream to which assuan should log message not associated
|
||||
with a context. By default, this is stderr. The default value
|
||||
will be changed when the first log stream is associated with a
|
||||
context. Note, that this function is not thread-safe and should
|
||||
in general be used right at startup. */
|
||||
extern void assuan_set_assuan_log_stream (FILE *fp);
|
||||
|
||||
/* Return the stream which is currently being using for global logging. */
|
||||
extern FILE *assuan_get_assuan_log_stream (void);
|
||||
|
||||
/* Set the prefix to be used at the start of a line emitted by assuan
|
||||
on the log stream. The default is the empty string. Note, that
|
||||
this function is not thread-safe and should in general be used
|
||||
right at startup. */
|
||||
void assuan_set_assuan_log_prefix (const char *text);
|
||||
|
||||
/* Return a prefix to be used at the start of a line emitted by assuan
|
||||
on the log stream. The default implementation returns the empty
|
||||
string, i.e. "" */
|
||||
const char *assuan_get_assuan_log_prefix (void);
|
||||
|
||||
#endif /* ASSUAN_H */
|
@ -1,5 +1,5 @@
|
||||
/* memory.h - memory allocation
|
||||
* 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.
|
||||
*
|
||||
@ -93,9 +93,9 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
|
||||
/* To prepare a migration to the xmalloc suite of function as used in
|
||||
1.9 we define a couple of macros. */
|
||||
#define xmalloc(n) m_alloc ((n))
|
||||
#define xcalloc(n,m) m_alloc_clear ((n)*(m))
|
||||
void *xcalloc (size_t n, size_t m);
|
||||
#define xmalloc_secure(n) m_alloc_secure (n)
|
||||
#define xcalloc_secure(n) m_alloc_secure_clear ((n)*(m))
|
||||
void *xcalloc_secure (size_t n, size_t m);
|
||||
#define xrealloc(a,n) m_realloc ((a),(n))
|
||||
#define xstrdup(a) m_strdup ((a))
|
||||
#define xfree(a) m_free (a)
|
||||
|
@ -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
|
||||
|
@ -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
480
util/assuan-buffer.c
Normal 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
280
util/assuan-client.c
Normal 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
95
util/assuan-connect.c
Normal 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
243
util/assuan-defs.h
Normal 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
104
util/assuan-errors.c
Normal 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
115
util/assuan-logging.c
Normal 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*/
|
190
util/assuan-socket-connect.c
Normal file
190
util/assuan-socket-connect.c
Normal 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
96
util/assuan-socket.c
Normal 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
170
util/assuan-util.c
Normal 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
29
util/isascii.c
Normal 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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user