Various fixes and new features.

Enhanced gpg-connect-agent.
This commit is contained in:
Werner Koch 2006-09-13 15:57:30 +00:00
parent 90af581b08
commit 9577dd45ab
20 changed files with 369 additions and 292 deletions

View File

@ -1,3 +1,7 @@
2006-09-13 Werner Koch <wk@g10code.com>
* autogen.sh: Better detection of the cross compiler kit.
2006-09-06 Marcus Brinkmann <marcus@g10code.de>
* configure.ac: New automake conditional RUN_GPG_TESTS.

16
NEWS
View File

@ -1,8 +1,8 @@
Noteworthy changes in version 1.9.23
-------------------------------------------------
* man pages for most tools are now build directly from the texinfo
source.
* Regular man pages for most tools are now build directly from the
texinfo source.
* The gpg code from 1.4.5 has been fully merged into this release.
The configure option --enable-gpg is still required to build this
@ -14,6 +14,18 @@ Noteworthy changes in version 1.9.23
* The scdaemon will now call a script on reader status changes.
* gpgsm now allows file descriptor passing for "INPUT", "OUTPUT" and
"MESSAGE".
* The gpgsm server may now output a key listing to the output file
handle. This needs to be enabled using "OPTION list-to-output=1".
* The --output option of gpgsm has now an effect on list-keys.
* New gpgsm commands --dump-chain and list-chain.
* gpg-connect-agent has new options to utilize descriptor passing.
Noteworthy changes in version 1.9.22 (2006-07-27)
-------------------------------------------------

View File

@ -1,4 +1,4 @@
If you are building from CVS, run the script
If you are building from Subversion, run the script
./autogen.sh

View File

@ -1,3 +1,11 @@
2006-09-13 Werner Koch <wk@g10code.com>
* preset-passphrase.c (main) [W32]: Check for WSAStartup error.
2006-09-08 Werner Koch <wk@g10code.com>
* call-scd.c: Add signal.h as we are referencing SIGUSR2.
2006-09-06 Marcus Brinkmann <marcus@g10code.de>
* Makefile.am (AM_CFLAGS): Add $(GPG_ERR_CFLAGS).

View File

@ -27,6 +27,7 @@
#include <ctype.h>
#include <assert.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#ifndef HAVE_W32_SYSTEM

View File

@ -281,10 +281,15 @@ main (int argc, char **argv)
#ifdef HAVE_W32_SYSTEM
/* Fixme: Need to initialize the Windows sockets: This should be
moved to another place and we should make sure that it won't get
doen twice, like when Pth is used too. */
done twice, like when Pth is used too. */
{
WSADATA wsadat;
WSAStartup (0x202, &wsadat);
if (WSAStartup (0x202, &wsadat) )
{
log_error ("error initializing socket library: ec=%d\n",
(int)WSAGetLastError () );
return 2;
}
}
#endif

View File

@ -55,36 +55,32 @@ if test "$1" = "--build-w32"; then
[ -z "$w32root" ] && w32root="$HOME/w32root"
echo "Using $w32root as standard install directory" >&2
# See whether we have the Debian cross compiler package or the
# old mingw32/cpd system
if i586-mingw32msvc-gcc --version >/dev/null 2>&1 ; then
host=i586-mingw32msvc
crossbindir=/usr/$host/bin
else
host=i386--mingw32
if ! mingw32 --version >/dev/null; then
echo "We need at least version 0.3 of MingW32/CPD" >&2
exit 1
fi
crossbindir=`mingw32 --install-dir`/bin
# Old autoconf version required us to setup the environment
# with the proper tool names.
CC=`mingw32 --get-path gcc`
CPP=`mingw32 --get-path cpp`
AR=`mingw32 --get-path ar`
RANLIB=`mingw32 --get-path ranlib`
export CC CPP AR RANLIB
# Locate the cross compiler
crossbindir=
for host in i586-mingw32msvc i386-mingw32msvc; do
if ${host}-gcc --version >/dev/null 2>&1 ; then
crossbindir=/usr/${host}/bin
conf_CC="CC=${host}-gcc"
break;
fi
done
if [ -z "$crossbindir" ]; then
echo "Cross compiler kit not installed" >&2
echo "Under Debian GNU/Linux, you may install it using" >&2
echo " apt-get install mingw32 mingw32-runtime mingw32-binutils" >&2
echo "Stop." >&2
exit 1
fi
if [ -f "$tsdir/config.log" ]; then
if ! head $tsdir/config.log | grep "$host" >/dev/null; then
echo "Pease run a 'make distclean' first" >&2
echo "Please run a 'make distclean' first" >&2
exit 1
fi
fi
./configure --enable-maintainer-mode --prefix=${w32root} \
--host=i586-mingw32msvc --build=${build} \
--host=${host} --build=${build} \
--with-gpg-error-prefix=${w32root} \
--with-ksba-prefix=${w32root} \
--with-libgcrypt-prefix=${w32root} \
@ -93,10 +89,6 @@ if test "$1" = "--build-w32"; then
--with-pth-prefix=${w32root} \
--disable-gpg
rc=$?
# Ugly hack to overcome a gettext problem. Someone should look into
# gettext to figure out why the po directory is not ignored as it used
# to be.
[ $rc = 0 ] && touch $tsdir/po/all
exit $rc
fi
# ***** end W32 build script *******

View File

@ -1,3 +1,12 @@
2006-09-13 Werner Koch <wk@g10code.com>
* gpg.texi (GPG Esoteric Options): Fixed typo in
--require-cross-certification and made it the default.
2006-09-11 Werner Koch <wk@g10code.com>
* HACKING: Cleaned up.
2006-09-08 Werner Koch <wk@g10code.com>
* yat2m.c (parse_file): Ignore @node lines immediately.

View File

@ -6,76 +6,6 @@
===> Under construction <=======
SOURCE FILES
============
Here is a list of directories with source files:
jnlib/ utility functions
kbx/ keybox library
g10/ the gpg program here called gpg2
sm/ the gpgsm program
agent/ the gpg-agent
scd/ the smartcard daemon
doc/ documentation
CVS Access
==========
NOTE: CVS access has been disabled while we are migrating to Subversion.
Watch www.gnupg.org for instarctions on how to use the Subversion repository.
Anonymous read-only CVS access is available:
cvs -z3 -d :pserver:anoncvs@cvs.gnupg.org:/cvs/gnupg login
use the password "anoncvs". To check out the the complete
archive use:
cvs -z3 -d :pserver:anoncvs@cvs.gnupg.org:/cvs/gnupg \
checkout -R STABLE-BRANCH-1-0 gnupg
This service is provided to help you in hunting bugs and not to deliver
stable snapshots; it may happen that it even does not compile, so please
don't complain. CVS may put a high load on a server, so please don't poll
poll for new updates but wait for an announcement; to receive this you may
want to subscribe to:
gnupg-commit-watchers@gnupg.org
by sending a mail with subject "subscribe" to
gnupg-commit-watchers-request@gnupg.org
You must run scripts/autogen.sh before doing the ./configure,
as this creates some needed while which are not in the CVS.
autogen.sh should checks that you have all required tools
installed.
RSYNC access
============
The FTP archive is also available by anonymous rsync. A daily snapshot
of the CVS head revision is also available. See rsync(1) and try
"rsync ftp.gnupg.org::" to see available resources.
Special Tools
=============
Documentation is based on the docbook DTD. Actually we have only the
man page for now. To build a man page you need the docbook-to-man
tool and all the other thinks needed for SGML processing. Debian
comes with the docbook tools and you only need this docbook-to-man
script which is comes with gtk-doc or download it from
ftp.openit.de:/pub/devel/sgml. If you don't have it everything
should still work fine but you will have only a dummy man page.
RFCs
====
@ -98,44 +28,23 @@ RFCs
Debug Flags
-----------
Use the option "--debug n" to output debug information. This option
can be used multiple times, all values are ORed; n maybe prefixed with
0x to use hex-values.
value used for
----- ----------------------------------------------
1 packet reading/writing
2 MPI details
4 ciphers and primes (may reveal sensitive data)
8 iobuf filter functions
16 iobuf stuff
32 memory allocation stuff
64 caching
128 show memory statistics at exit
256 trust verification stuff
Directory Layout
----------------
./ Readme, configure
./scripts Scripts needed by configure and others
./doc Documentation
./util General purpose utility function
./mpi Multi precision integer library
./cipher Cryptographic functions
./g10 GnuPG application
./tools Some helper and demo programs
./keybox The keybox library (under construction)
./gcrypt Stuff needed to build libgcrypt (under construction)
./ Readme, configure
./agent Gpg-agent and related tools
./doc Documentation
./doc Documentation
./g10 Gpg program here called gpg2
./jnlib Utility functions
./kbx Keybox library
./scd Smartcard daemon
./scripts Scripts needed by configure and others
./sm Gpgsm program
Detailed Roadmap
----------------
g10/g10.c Main module with option parsing and all the stuff you have
g10/gpg.c Main module with option parsing and all the stuff you have
to do on startup. Also has the exout handler and some
helper functions.
g10/sign.c Create signature and optionally encrypt
@ -208,17 +117,28 @@ Memory allocation
-----------------
Use only the functions:
m_alloc()
m_alloc_clear()
m_strdup()
m_free()
xmalloc
xmalloc_secure
xtrymalloc
xtrymalloc_secure
xcalloc
xcalloc_secure
xtrycalloc
xtrycalloc_secure
xrealloc
xtryrealloc
xstrdup
xtrystrdup
xfree
If you want to store a passphrase or some other sensitive data you may
want to use m_alloc_secure() instead of m_alloc(), as this puts the data
into a memory region which is protected from swapping (on some platforms).
m_free() works for both. This functions will not return if there is not
enough memory available.
The *secure versions allocated memory in the secure memory. That is,
swapping out of this memory is avoided and is gets overwritten on
free. Use this for passphrases, session keys and other sensitive
material. This memory set aside for secure memory is linited to a few
k. In general the function don't print a memeory message and
terminate the process if there is not enough memory available. The
"try" versions of the functions return NULL instead.
Logging
@ -254,68 +174,3 @@ the other way: constructing messages using pushed filters but it may be
easier to understand.
How to use the message digest functions
---------------------------------------
cipher/md.c implements an interface to hash (message digest functions).
a) If you have a common part of data and some variable parts
and you need to hash of the concatenated parts, you can use this:
md = md_open(...)
md_write( md, common_part )
md1 = md_copy( md )
md_write(md1, part1)
md_final(md1);
digest1 = md_read(md1)
md2 = md_copy( md )
md_write(md2, part2)
md_final(md2);
digest2 = md_read(md2)
An example are key signatures; the key packet is the common part
and the user-id packets are the variable parts.
b) If you need a running digest you should use this:
md = md_open(...)
md_write( md, part1 )
digest_of_part1 = md_digest( md );
md_write( md, part2 )
digest_of_part1_cat_part2 = md_digest( md );
....
Both methods may be combined. [Please see the source for the real syntax]
How to use the cipher functions
-------------------------------
cipher/cipher.c implements the interface to symmetric encryption functions.
As usual you have a function to open a cipher (which returns a handle to be used
with all other functions), some functions to set the key and other stuff and
a encrypt and decrypt function which does the real work. You probably know
how to work with files - so it should really be easy to work with these
functions. Here is an example:
CIPHER_HANDLE hd;
hd = cipher_open( CIPHER_ALGO_TWOFISH, CIPHER_MODE_CFB, 0 );
if( !hd )
oops( use other function to check for the real error );
rc = cipher_setkey( hd, key256bit, 32 ) )
if( rc )
oops( weak key or something like this );
cipher_setiv( hd, some_IV_or_NULL_for_all_zeroes );
cipher_encrypt( hd, plain, cipher, size );
cipher_close( hd );
How to use the public key functions
-----------------------------------
cipher/pubkey.c implements the interface to asymmetric encryption and
signature functions. This is basically the same as with the symmetric
counterparts, but due to their nature it is a little bit more complicated.
[Give an example]

View File

@ -2178,12 +2178,11 @@ content of an encrypted message; using this option you can do this without
handing out the secret key.
@item --require-cross-certification
@itemx --no-require-certification
@itemx --no-require-cross-certification
When verifying a signature made from a subkey, ensure that the cross
certification "back signature" on the subkey is present and valid.
This protects against a subtle attack against subkeys that can sign.
Currently defaults to --no-require-cross-certification, but will be
changed to --require-cross-certification in the future.
Defaults to --require-cross-certification for @command{gpg2}.
@item --ask-sig-expire
@itemx --no-ask-sig-expire

View File

@ -184,11 +184,20 @@ is available.
List certificates matching @var{pattern} using an external server. This
utilizes the @code{dirmngr} service.
@item --list-chain
@opindex list-chain
Same as @option{--list-keys} but also prints all keys making up the chain.
@item --dump-keys
@opindex dump-keys
List all available certificates stored in the local key database using a
format useful mainly for debugging.
@item --dump-chain
@opindex dump-chain
Same as @option{--dump-keys} but also prints all keys making up the chain.
@item --dump-secret-keys
@opindex dump-secret-keys
List all available certificates for which a corresponding a secret key

View File

@ -989,6 +989,22 @@ Connect to socket @var{name} assuming this is an Assuan style server.
Do not run any special initializations or environment checks. This may
be used to directly connect to any Assuan style socket server.
@item -E
@itemx --exec
@opindex exec
Take the rest of the command line as a program and it's arguments and
execute it as an assuan server. Here is how you would run @command{gpgsm}:
@smallexample
gpg-connect-agent --exec gpgsm --server
@end smallexample
@item --no-ext-connect
@opindex no-ext-connect
When using @option{-S} or @option{--exec}, @command{gpg-connect-agent}
connects to the assuan server in extended mode to allow descriptor
passing. This option makes it use the old mode.
@end table
@mansect control commands
@ -1020,6 +1036,15 @@ Print all definitions
@item /cleardef
Delete all definitions
@item /sendfd @var{file} @var{mode}
Open @var{file} in @var{mode} (which needs to be a valid @code{fopen}
mode string) and send the file descriptor to the server. This is
usually followed by a command like @code{INPUT FD} to set the
input source for other commands.
@item /recvfd
Not yet implemented.
@item /help
Print a list of available control commands.

View File

@ -1,3 +1,7 @@
2006-09-13 Werner Koch <wk@g10code.com>
* gpg.c (main): Made --require-cross-certification the default.
2006-09-06 Marcus Brinkmann <marcus@g10code.de>
* Makefile.am (gpg2_LDADD, gpgv2_LDADD): Replace -lassuan and

View File

@ -1834,6 +1834,7 @@ main (int argc, char **argv )
opt.rfc2440_text=1;
opt.def_sig_expire="0";
opt.def_cert_expire="0";
opt.require_cross_cert = 1;
set_homedir ( default_homedir () );
/* Check whether we have a config file on the command line. */

View File

@ -1,3 +1,17 @@
2006-09-13 Werner Koch <wk@g10code.com>
* keylist.c (list_internal_keys): Print marker line to FP and not
to stdout.
* gpgsm.c (main): All list key list commands now make ose of
--output. Cleaned up calls to list modes. New command
--dump-chain. Renamed --list-sigs to --list-chain and added an
alias for the old one.
* server.c (cmd_message): Changed to use assuan_command_parse_fd.
(option_handler): New option list-to-output.
(do_listkeys): Use it.
2006-09-06 Werner Koch <wk@g10code.com>
* gpgsm.h (OUT_OF_CORE): Removed and changed all callers to

View File

@ -80,7 +80,7 @@ enum cmd_and_opt_values {
aVerify,
aVerifyFiles,
aListExternalKeys,
aListSigs,
aListChain,
aSendKeys,
aRecvKeys,
aExport,
@ -93,6 +93,7 @@ enum cmd_and_opt_values {
aPasswd,
aGPGConfList,
aDumpKeys,
aDumpChain,
aDumpSecretKeys,
aDumpExternalKeys,
aKeydbClearSomeCertFlags,
@ -251,8 +252,7 @@ static ARGPARSE_OPTS opts[] = {
{ aListKeys, "list-keys", 256, N_("list keys")},
{ aListExternalKeys, "list-external-keys", 256, N_("list external keys")},
{ aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")},
{ aListSigs, "list-sigs", 256, N_("list certificate chain")},
{ aListSigs, "check-sigs",256, "@"},
{ aListChain, "list-chain", 256, N_("list certificate chain")},
{ oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")},
{ aKeygen, "gen-key", 256, N_("generate a new key pair")},
{ aDeleteKey, "delete-key",256, N_("remove key from the public keyring")},
@ -269,6 +269,7 @@ static ARGPARSE_OPTS opts[] = {
{ aGPGConfList, "gpgconf-list", 256, "@" },
{ aDumpKeys, "dump-keys", 256, "@"},
{ aDumpChain, "dump-chain", 256, "@"},
{ aDumpExternalKeys, "dump-external-keys", 256, "@"},
{ aDumpSecretKeys, "dump-secret-keys", 256, "@"},
{ aKeydbClearSomeCertFlags, "keydb-clear-some-cert-flags", 256, "@"},
@ -428,9 +429,11 @@ static ARGPARSE_OPTS opts[] = {
{ oWithValidation, "with-validation", 0, "@"},
{ oWithMD5Fingerprint, "with-md5-fingerprint", 0, "@"},
{ oWithEphemeralKeys, "with-ephemeral-keys", 0, "@"},
{ aListKeys, "list-key", 0, "@" }, /* alias */
{ aListSigs, "list-sig", 0, "@" }, /* alias */
{ aListSigs, "check-sig",0, "@" }, /* alias */
{ aListKeys, "list-key", 256, "@" }, /* alias */
{ aListChain, "list-sig", 256, "@" }, /* alias */
{ aListChain, "list-sigs",256, "@" }, /* alias */
{ aListChain, "check-sig",256, "@" }, /* alias */
{ aListChain, "check-sigs",256, "@"}, /* alias */
{ oSkipVerify, "skip-verify",0, "@" },
{ oCompressKeys, "compress-keys",0, "@"},
{ oCompressSigs, "compress-sigs",0, "@"},
@ -930,12 +933,13 @@ main ( int argc, char **argv)
case aExport:
case aExportSecretKeyP12:
case aDumpKeys:
case aDumpChain:
case aDumpExternalKeys:
case aDumpSecretKeys:
case aListKeys:
case aListExternalKeys:
case aListSecretKeys:
case aListSigs:
case aListChain:
case aLearnCard:
case aPasswd:
case aKeydbClearSomeCertFlags:
@ -1518,51 +1522,42 @@ main ( int argc, char **argv)
free_strlist(sl);
break;
case aListSigs:
ctrl.with_chain = 1;
case aListChain:
case aDumpChain:
ctrl.with_chain = 1;
case aListKeys:
for (sl=NULL; argc; argc--, argv++)
add_to_strlist (&sl, *argv);
gpgsm_list_keys (&ctrl, sl, stdout, (0 | (1<<6)));
free_strlist(sl);
break;
case aDumpKeys:
for (sl=NULL; argc; argc--, argv++)
add_to_strlist (&sl, *argv);
gpgsm_list_keys (&ctrl, sl, stdout, (256 | (1<<6)));
free_strlist(sl);
break;
case aListExternalKeys:
for (sl=NULL; argc; argc--, argv++)
add_to_strlist (&sl, *argv);
gpgsm_list_keys (&ctrl, sl, stdout,
(0 | (1<<7)));
free_strlist(sl);
break;
case aDumpExternalKeys:
for (sl=NULL; argc; argc--, argv++)
add_to_strlist (&sl, *argv);
gpgsm_list_keys (&ctrl, sl, stdout,
(256 | (1<<7)));
free_strlist(sl);
break;
case aListSecretKeys:
for (sl=NULL; argc; argc--, argv++)
add_to_strlist (&sl, *argv);
gpgsm_list_keys (&ctrl, sl, stdout, (2 | (1<<6)));
free_strlist(sl);
case aDumpSecretKeys:
{
unsigned int mode;
FILE *fp;
switch (cmd)
{
case aListChain:
case aListKeys: mode = (0 | 0 | (1<<6)); break;
case aDumpChain:
case aDumpKeys: mode = (256 | 0 | (1<<6)); break;
case aListExternalKeys: mode = (0 | 0 | (1<<7)); break;
case aDumpExternalKeys: mode = (256 | 0 | (1<<7)); break;
case aListSecretKeys: mode = (0 | 2 | (1<<6)); break;
case aDumpSecretKeys: mode = (256 | 2 | (1<<6)); break;
default: BUG();
}
fp = open_fwrite (opt.outfile?opt.outfile:"-");
for (sl=NULL; argc; argc--, argv++)
add_to_strlist (&sl, *argv);
gpgsm_list_keys (&ctrl, sl, fp, mode);
free_strlist(sl);
if (fp != stdout)
fclose (fp);
}
break;
case aDumpSecretKeys:
for (sl=NULL; argc; argc--, argv++)
add_to_strlist (&sl, *argv);
gpgsm_list_keys (&ctrl, sl, stdout, (256 | 2 | (1<<6)));
free_strlist(sl);
break;
case aKeygen: /* generate a key */
log_error ("this function is not yet available from the commandline\n");

View File

@ -1130,7 +1130,7 @@ list_cert_chain (ctrl_t ctrl, KEYDB_HANDLE hd,
/* List all internal keys or just the keys given as NAMES. MODE is a
bit vector to specify what keys are to be included; see
gpgsm_list_keys (below) for details. If RAW_MODE is true, the raw
output mode will be used intead of the standard beautified one.
output mode will be used instead of the standard beautified one.
*/
static gpg_error_t
list_internal_keys (ctrl_t ctrl, STRLIST names, FILE *fp,
@ -1229,7 +1229,7 @@ list_internal_keys (ctrl_t ctrl, STRLIST names, FILE *fp,
{
fprintf (fp, "%s\n", resname );
for (i=strlen(resname); i; i-- )
putchar('-');
putc ('-', fp);
putc ('\n', fp);
lastresname = resname;
}

View File

@ -44,6 +44,7 @@ struct server_local_s {
int message_fd;
int list_internal;
int list_external;
int list_to_output; /* Write keylistings to the output fd. */
certlist_t recplist;
certlist_t signerlist;
certlist_t default_recplist; /* As set by main() - don't release. */
@ -171,6 +172,11 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
else
return gpg_error (GPG_ERR_ASS_PARAMETER);
}
else if (!strcmp (key, "list-to-output"))
{
int i = *value? atoi (value) : 0;
ctrl->server_local->list_to_output = i;
}
else if (!strcmp (key, "with-validation"))
{
int i = *value? atoi (value) : 0;
@ -624,40 +630,33 @@ cmd_delkeys (assuan_context_t ctx, char *line)
static int
cmd_message (assuan_context_t ctx, char *line)
{
char *endp;
int rc;
int fd;
ctrl_t ctrl = assuan_get_pointer (ctx);
if (strncmp (line, "FD=", 3))
return set_error (GPG_ERR_ASS_SYNTAX, "FD=<n> expected");
line += 3;
if (!digitp (line))
return set_error (GPG_ERR_ASS_SYNTAX, "number required");
fd = strtoul (line, &endp, 10);
if (*endp)
return set_error (GPG_ERR_ASS_SYNTAX, "garbage found");
rc = assuan_command_parse_fd (ctx, line, &fd);
if (rc)
return rc;
if (fd == -1)
return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
ctrl->server_local->message_fd = fd;
return 0;
}
/* LISTKEYS [<patterns>]
LISTSECRETKEYS [<patterns>]
*/
static int
do_listkeys (assuan_context_t ctx, char *line, int mode)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
FILE *fp = assuan_get_data_fp (ctx);
FILE *fp;
char *p;
STRLIST list, sl;
unsigned int listmode;
gpg_error_t err;
if (!fp)
return set_error (GPG_ERR_ASS_GENERAL, "no data stream");
/* break the line down into an STRLIST */
/* Break the line down into an STRLIST. */
list = NULL;
for (p=line; *p; line = p)
{
@ -680,6 +679,21 @@ do_listkeys (assuan_context_t ctx, char *line, int mode)
}
}
if (ctrl->server_local->list_to_output)
{
if ( assuan_get_output_fd (ctx) == -1 )
return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
fp = fdopen (assuan_get_output_fd (ctx), "w");
if (!fp)
return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
}
else
{
fp = assuan_get_data_fp (ctx);
if (!fp)
return set_error (GPG_ERR_ASS_GENERAL, "no data stream");
}
ctrl->with_colons = 1;
listmode = mode;
if (ctrl->server_local->list_internal)
@ -688,6 +702,11 @@ do_listkeys (assuan_context_t ctx, char *line, int mode)
listmode |= (1<<7);
err = gpgsm_list_keys (assuan_get_pointer (ctx), list, fp, listmode);
free_strlist (list);
if (ctrl->server_local->list_to_output)
{
fclose (fp);
assuan_close_output_fd (ctx);
}
return err;
}
@ -793,9 +812,9 @@ gpgsm_server (certlist_t default_recplist)
memset (&ctrl, 0, sizeof ctrl);
gpgsm_init_default_ctrl (&ctrl);
/* For now we use a simple pipe based server so that we can work
from scripts. We will later add options to run as a daemon and
wait for requests on a Unix domain socket */
/* We use a pipe based server so that we can work from scripts.
assuan_init_pipe_server will automagically detect when we are
called with a socketpair and ignore FIELDES in this case. */
filedes[0] = 0;
filedes[1] = 1;
rc = assuan_init_pipe_server (&ctx, filedes);

View File

@ -1,3 +1,8 @@
2006-09-12 Werner Koch <wk@g10code.com>
* gpg-connect-agent.c (read_and_print_response): With verbosity
level 2 also print comment lines.
2006-09-06 Werner Koch <wk@g10code.com>
* gpg-connect-agent.c: Switch everything to new Assuan error code

View File

@ -41,10 +41,12 @@ enum cmd_and_opt_values
oQuiet = 'q',
oVerbose = 'v',
oRawSocket = 'S',
oExec = 'E',
oNoVerbose = 500,
oHomedir,
oHex
oHex,
oNoExtConnect
};
@ -58,6 +60,9 @@ static ARGPARSE_OPTS opts[] =
{ oQuiet, "quiet", 0, N_("quiet") },
{ oHex, "hex", 0, N_("print data out hex encoded") },
{ oRawSocket, "raw-socket", 2, N_("|NAME|connect to Assuan socket NAME")},
{ oExec, "exec", 0, N_("run the Assuan server given on the command line")},
{ oNoExtConnect, "no-ext-connect",
0, N_("do not use extended connect mode")},
/* hidden options */
{ oNoVerbose, "no-verbose", 0, "@"},
@ -74,6 +79,8 @@ struct
const char *homedir; /* Configuration directory name */
int hex; /* Print data lines in hex format. */
const char *raw_socket; /* Name of socket to connect in raw mode. */
int exec; /* Run the pgm given on the command line. */
unsigned int connect_flags; /* Flags used for connecting. */
} opt;
@ -209,13 +216,68 @@ clear_definq (void)
}
static void
do_sendfd (assuan_context_t ctx, char *line)
{
FILE *fp;
char *name, *mode, *p;
int rc, fd;
/* Get file name. */
name = line;
for (p=name; *p && !spacep (p); p++)
;
if (*p)
*p++ = 0;
while (spacep (p))
p++;
/* Get mode. */
mode = p;
if (!*mode)
mode = "r";
else
{
for (p=mode; *p && !spacep (p); p++)
;
if (*p)
*p++ = 0;
}
/* Open and send. */
fp = fopen (name, mode);
if (!fp)
{
log_error ("can't open `%s' in \"%s\" mode: %s\n",
name, mode, strerror (errno));
return;
}
fd = fileno (fp);
if (opt.verbose)
log_error ("file `%s' opened in \"%s\" mode, fd=%d\n",
name, mode, fd);
rc = assuan_sendfd (ctx, fd);
if (rc)
log_error ("sednig descriptor %d failed: %s\n", fd, gpg_strerror (rc));
fclose (fp);
}
static void
do_recvfd (assuan_context_t ctx, char *line)
{
log_info ("This command has not yet been implemented\n");
}
/* gpg-connect-agent's entry point. */
int
main (int argc, char **argv)
{
ARGPARSE_ARGS pargs;
const char *fname;
int no_more_options = 0;
assuan_context_t ctx;
char *line, *p;
@ -229,6 +291,7 @@ main (int argc, char **argv)
i18n_init();
opt.homedir = default_homedir ();
opt.connect_flags = 1; /* Use extended connect mode. */
/* Parse the command line. */
pargs.argc = &argc;
@ -244,6 +307,8 @@ main (int argc, char **argv)
case oHomedir: opt.homedir = pargs.r.ret_str; break;
case oHex: opt.hex = 1; break;
case oRawSocket: opt.raw_socket = pargs.r.ret_str; break;
case oExec: opt.exec = 1; break;
case oNoExtConnect: opt.connect_flags &= ~(1); break;
default: pargs.err = 2; break;
}
@ -251,12 +316,48 @@ main (int argc, char **argv)
if (log_get_errorcount (0))
exit (2);
fname = argc ? *argv : NULL;
if (opt.raw_socket)
if (opt.exec)
{
rc = assuan_socket_connect (&ctx, opt.raw_socket, 0);
if (!argc)
{
log_error (_("option \"%s\" requires a program "
"and optional arguments\n"), "--exec" );
exit (1);
}
}
else if (argc)
usage (1);
if (opt.exec && opt.raw_socket)
log_info (_("option \"%s\" ignored due to \"%s\"\n"),
"--raw-socket", "--exec");
if (opt.exec)
{
int no_close[3];
no_close[0] = fileno (stderr);
no_close[1] = log_get_fd ();
no_close[2] = -1;
rc = assuan_pipe_connect_ext (&ctx, *argv, (const char **)argv,
no_close, NULL, NULL,
opt.connect_flags);
if (rc)
{
log_error ("assuan_pipe_connect_ext failed: %s\n",
gpg_strerror (rc));
exit (1);
}
if (opt.verbose)
log_info ("server `%s' started\n", *argv);
}
else if (opt.raw_socket)
{
rc = assuan_socket_connect_ext (&ctx, opt.raw_socket, 0,
opt.connect_flags);
if (rc)
{
log_error ("can't connect to socket `%s': %s\n",
@ -325,18 +426,31 @@ main (int argc, char **argv)
{
puts (p);
}
else if (!strcmp (cmd, "sendfd"))
{
do_sendfd (ctx, p);
continue;
}
else if (!strcmp (cmd, "recvfd"))
{
do_recvfd (ctx, p);
continue;
}
else if (!strcmp (cmd, "help"))
{
puts ("Available commands:\n"
"/echo ARGS Echo ARGS.\n"
"/definqfile NAME FILE\n"
" Use content of FILE for inquiries with NAME.\n"
" NAME may be \"*\" to match any inquiry.\n"
"/definqprog NAME PGM\n"
" Run PGM for inquiries matching NAME and pass the\n"
" entire line to it as arguments.\n"
"/showdef Print all definitions.\n"
"/cleardef Delete all definitions.\n"
puts (
"Available commands:\n"
"/echo ARGS Echo ARGS.\n"
"/definqfile NAME FILE\n"
" Use content of FILE for inquiries with NAME.\n"
" NAME may be \"*\" to match any inquiry.\n"
"/definqprog NAME PGM\n"
" Run PGM for inquiries matching NAME and pass the\n"
" entire line to it as arguments.\n"
"/showdef Print all definitions.\n"
"/cleardef Delete all definitions.\n"
"/sendfd FILE MODE Open FILE and pass descripor to server.\n"
"/recvfd Receive FD from server and print. \n"
"/help Print this help.");
}
else
@ -352,7 +466,7 @@ main (int argc, char **argv)
continue;
}
if (*line == '#' || !*line)
continue; /* Don't expect a response for a coment line. */
continue; /* Don't expect a response for a comment line. */
rc = read_and_print_response (ctx);
if (rc)
@ -471,6 +585,12 @@ read_and_print_response (assuan_context_t ctx)
rc = assuan_read_line (ctx, &line, &linelen);
if (rc)
return rc;
if (opt.verbose > 1 && *line == '#')
{
fwrite (line, linelen, 1, stdout);
putchar ('\n');
}
}
while (*line == '#' || !linelen);