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> 2006-09-06 Marcus Brinkmann <marcus@g10code.de>
* configure.ac: New automake conditional RUN_GPG_TESTS. * configure.ac: New automake conditional RUN_GPG_TESTS.

16
NEWS
View File

@ -1,8 +1,8 @@
Noteworthy changes in version 1.9.23 Noteworthy changes in version 1.9.23
------------------------------------------------- -------------------------------------------------
* man pages for most tools are now build directly from the texinfo * Regular man pages for most tools are now build directly from the
source. texinfo source.
* The gpg code from 1.4.5 has been fully merged into this release. * 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 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. * 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) 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 ./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> 2006-09-06 Marcus Brinkmann <marcus@g10code.de>
* Makefile.am (AM_CFLAGS): Add $(GPG_ERR_CFLAGS). * Makefile.am (AM_CFLAGS): Add $(GPG_ERR_CFLAGS).

View File

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

View File

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

View File

@ -55,36 +55,32 @@ if test "$1" = "--build-w32"; then
[ -z "$w32root" ] && w32root="$HOME/w32root" [ -z "$w32root" ] && w32root="$HOME/w32root"
echo "Using $w32root as standard install directory" >&2 echo "Using $w32root as standard install directory" >&2
# See whether we have the Debian cross compiler package or the # Locate the cross compiler
# old mingw32/cpd system crossbindir=
if i586-mingw32msvc-gcc --version >/dev/null 2>&1 ; then for host in i586-mingw32msvc i386-mingw32msvc; do
host=i586-mingw32msvc if ${host}-gcc --version >/dev/null 2>&1 ; then
crossbindir=/usr/$host/bin crossbindir=/usr/${host}/bin
else conf_CC="CC=${host}-gcc"
host=i386--mingw32 break;
if ! mingw32 --version >/dev/null; then fi
echo "We need at least version 0.3 of MingW32/CPD" >&2 done
exit 1 if [ -z "$crossbindir" ]; then
fi echo "Cross compiler kit not installed" >&2
crossbindir=`mingw32 --install-dir`/bin echo "Under Debian GNU/Linux, you may install it using" >&2
# Old autoconf version required us to setup the environment echo " apt-get install mingw32 mingw32-runtime mingw32-binutils" >&2
# with the proper tool names. echo "Stop." >&2
CC=`mingw32 --get-path gcc` exit 1
CPP=`mingw32 --get-path cpp`
AR=`mingw32 --get-path ar`
RANLIB=`mingw32 --get-path ranlib`
export CC CPP AR RANLIB
fi fi
if [ -f "$tsdir/config.log" ]; then if [ -f "$tsdir/config.log" ]; then
if ! head $tsdir/config.log | grep "$host" >/dev/null; 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 exit 1
fi fi
fi fi
./configure --enable-maintainer-mode --prefix=${w32root} \ ./configure --enable-maintainer-mode --prefix=${w32root} \
--host=i586-mingw32msvc --build=${build} \ --host=${host} --build=${build} \
--with-gpg-error-prefix=${w32root} \ --with-gpg-error-prefix=${w32root} \
--with-ksba-prefix=${w32root} \ --with-ksba-prefix=${w32root} \
--with-libgcrypt-prefix=${w32root} \ --with-libgcrypt-prefix=${w32root} \
@ -93,10 +89,6 @@ if test "$1" = "--build-w32"; then
--with-pth-prefix=${w32root} \ --with-pth-prefix=${w32root} \
--disable-gpg --disable-gpg
rc=$? 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 exit $rc
fi fi
# ***** end W32 build script ******* # ***** 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> 2006-09-08 Werner Koch <wk@g10code.com>
* yat2m.c (parse_file): Ignore @node lines immediately. * yat2m.c (parse_file): Ignore @node lines immediately.

View File

@ -6,76 +6,6 @@
===> Under construction <======= ===> 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 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 Directory Layout
---------------- ----------------
./ Readme, configure ./ Readme, configure
./scripts Scripts needed by configure and others ./agent Gpg-agent and related tools
./doc Documentation ./doc Documentation
./util General purpose utility function ./doc Documentation
./mpi Multi precision integer library ./g10 Gpg program here called gpg2
./cipher Cryptographic functions ./jnlib Utility functions
./g10 GnuPG application ./kbx Keybox library
./tools Some helper and demo programs ./scd Smartcard daemon
./keybox The keybox library (under construction) ./scripts Scripts needed by configure and others
./gcrypt Stuff needed to build libgcrypt (under construction) ./sm Gpgsm program
Detailed Roadmap 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 to do on startup. Also has the exout handler and some
helper functions. helper functions.
g10/sign.c Create signature and optionally encrypt g10/sign.c Create signature and optionally encrypt
@ -208,17 +117,28 @@ Memory allocation
----------------- -----------------
Use only the functions: Use only the functions:
m_alloc() xmalloc
m_alloc_clear() xmalloc_secure
m_strdup() xtrymalloc
m_free() 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 Logging
@ -254,68 +174,3 @@ the other way: constructing messages using pushed filters but it may be
easier to understand. 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. handing out the secret key.
@item --require-cross-certification @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 When verifying a signature made from a subkey, ensure that the cross
certification "back signature" on the subkey is present and valid. certification "back signature" on the subkey is present and valid.
This protects against a subtle attack against subkeys that can sign. This protects against a subtle attack against subkeys that can sign.
Currently defaults to --no-require-cross-certification, but will be Defaults to --require-cross-certification for @command{gpg2}.
changed to --require-cross-certification in the future.
@item --ask-sig-expire @item --ask-sig-expire
@itemx --no-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 List certificates matching @var{pattern} using an external server. This
utilizes the @code{dirmngr} service. 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 @item --dump-keys
@opindex dump-keys @opindex dump-keys
List all available certificates stored in the local key database using a List all available certificates stored in the local key database using a
format useful mainly for debugging. 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 @item --dump-secret-keys
@opindex dump-secret-keys @opindex dump-secret-keys
List all available certificates for which a corresponding a secret key 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 Do not run any special initializations or environment checks. This may
be used to directly connect to any Assuan style socket server. 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 @end table
@mansect control commands @mansect control commands
@ -1020,6 +1036,15 @@ Print all definitions
@item /cleardef @item /cleardef
Delete all definitions 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 @item /help
Print a list of available control commands. 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> 2006-09-06 Marcus Brinkmann <marcus@g10code.de>
* Makefile.am (gpg2_LDADD, gpgv2_LDADD): Replace -lassuan and * 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.rfc2440_text=1;
opt.def_sig_expire="0"; opt.def_sig_expire="0";
opt.def_cert_expire="0"; opt.def_cert_expire="0";
opt.require_cross_cert = 1;
set_homedir ( default_homedir () ); set_homedir ( default_homedir () );
/* Check whether we have a config file on the command line. */ /* 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> 2006-09-06 Werner Koch <wk@g10code.com>
* gpgsm.h (OUT_OF_CORE): Removed and changed all callers to * gpgsm.h (OUT_OF_CORE): Removed and changed all callers to

View File

@ -80,7 +80,7 @@ enum cmd_and_opt_values {
aVerify, aVerify,
aVerifyFiles, aVerifyFiles,
aListExternalKeys, aListExternalKeys,
aListSigs, aListChain,
aSendKeys, aSendKeys,
aRecvKeys, aRecvKeys,
aExport, aExport,
@ -93,6 +93,7 @@ enum cmd_and_opt_values {
aPasswd, aPasswd,
aGPGConfList, aGPGConfList,
aDumpKeys, aDumpKeys,
aDumpChain,
aDumpSecretKeys, aDumpSecretKeys,
aDumpExternalKeys, aDumpExternalKeys,
aKeydbClearSomeCertFlags, aKeydbClearSomeCertFlags,
@ -251,8 +252,7 @@ static ARGPARSE_OPTS opts[] = {
{ aListKeys, "list-keys", 256, N_("list keys")}, { aListKeys, "list-keys", 256, N_("list keys")},
{ aListExternalKeys, "list-external-keys", 256, N_("list external keys")}, { aListExternalKeys, "list-external-keys", 256, N_("list external keys")},
{ aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")}, { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")},
{ aListSigs, "list-sigs", 256, N_("list certificate chain")}, { aListChain, "list-chain", 256, N_("list certificate chain")},
{ aListSigs, "check-sigs",256, "@"},
{ oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")}, { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")},
{ aKeygen, "gen-key", 256, N_("generate a new key pair")}, { aKeygen, "gen-key", 256, N_("generate a new key pair")},
{ aDeleteKey, "delete-key",256, N_("remove key from the public keyring")}, { aDeleteKey, "delete-key",256, N_("remove key from the public keyring")},
@ -269,6 +269,7 @@ static ARGPARSE_OPTS opts[] = {
{ aGPGConfList, "gpgconf-list", 256, "@" }, { aGPGConfList, "gpgconf-list", 256, "@" },
{ aDumpKeys, "dump-keys", 256, "@"}, { aDumpKeys, "dump-keys", 256, "@"},
{ aDumpChain, "dump-chain", 256, "@"},
{ aDumpExternalKeys, "dump-external-keys", 256, "@"}, { aDumpExternalKeys, "dump-external-keys", 256, "@"},
{ aDumpSecretKeys, "dump-secret-keys", 256, "@"}, { aDumpSecretKeys, "dump-secret-keys", 256, "@"},
{ aKeydbClearSomeCertFlags, "keydb-clear-some-cert-flags", 256, "@"}, { aKeydbClearSomeCertFlags, "keydb-clear-some-cert-flags", 256, "@"},
@ -428,9 +429,11 @@ static ARGPARSE_OPTS opts[] = {
{ oWithValidation, "with-validation", 0, "@"}, { oWithValidation, "with-validation", 0, "@"},
{ oWithMD5Fingerprint, "with-md5-fingerprint", 0, "@"}, { oWithMD5Fingerprint, "with-md5-fingerprint", 0, "@"},
{ oWithEphemeralKeys, "with-ephemeral-keys", 0, "@"}, { oWithEphemeralKeys, "with-ephemeral-keys", 0, "@"},
{ aListKeys, "list-key", 0, "@" }, /* alias */ { aListKeys, "list-key", 256, "@" }, /* alias */
{ aListSigs, "list-sig", 0, "@" }, /* alias */ { aListChain, "list-sig", 256, "@" }, /* alias */
{ aListSigs, "check-sig",0, "@" }, /* alias */ { aListChain, "list-sigs",256, "@" }, /* alias */
{ aListChain, "check-sig",256, "@" }, /* alias */
{ aListChain, "check-sigs",256, "@"}, /* alias */
{ oSkipVerify, "skip-verify",0, "@" }, { oSkipVerify, "skip-verify",0, "@" },
{ oCompressKeys, "compress-keys",0, "@"}, { oCompressKeys, "compress-keys",0, "@"},
{ oCompressSigs, "compress-sigs",0, "@"}, { oCompressSigs, "compress-sigs",0, "@"},
@ -930,12 +933,13 @@ main ( int argc, char **argv)
case aExport: case aExport:
case aExportSecretKeyP12: case aExportSecretKeyP12:
case aDumpKeys: case aDumpKeys:
case aDumpChain:
case aDumpExternalKeys: case aDumpExternalKeys:
case aDumpSecretKeys: case aDumpSecretKeys:
case aListKeys: case aListKeys:
case aListExternalKeys: case aListExternalKeys:
case aListSecretKeys: case aListSecretKeys:
case aListSigs: case aListChain:
case aLearnCard: case aLearnCard:
case aPasswd: case aPasswd:
case aKeydbClearSomeCertFlags: case aKeydbClearSomeCertFlags:
@ -1518,51 +1522,42 @@ main ( int argc, char **argv)
free_strlist(sl); free_strlist(sl);
break; break;
case aListSigs: case aListChain:
ctrl.with_chain = 1; case aDumpChain:
ctrl.with_chain = 1;
case aListKeys: 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: 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: 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: 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: case aListSecretKeys:
for (sl=NULL; argc; argc--, argv++) case aDumpSecretKeys:
add_to_strlist (&sl, *argv); {
gpgsm_list_keys (&ctrl, sl, stdout, (2 | (1<<6))); unsigned int mode;
free_strlist(sl); 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; 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 */ case aKeygen: /* generate a key */
log_error ("this function is not yet available from the commandline\n"); 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 /* 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 bit vector to specify what keys are to be included; see
gpgsm_list_keys (below) for details. If RAW_MODE is true, the raw 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 static gpg_error_t
list_internal_keys (ctrl_t ctrl, STRLIST names, FILE *fp, 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 ); fprintf (fp, "%s\n", resname );
for (i=strlen(resname); i; i-- ) for (i=strlen(resname); i; i-- )
putchar('-'); putc ('-', fp);
putc ('\n', fp); putc ('\n', fp);
lastresname = resname; lastresname = resname;
} }

View File

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

View File

@ -41,10 +41,12 @@ enum cmd_and_opt_values
oQuiet = 'q', oQuiet = 'q',
oVerbose = 'v', oVerbose = 'v',
oRawSocket = 'S', oRawSocket = 'S',
oExec = 'E',
oNoVerbose = 500, oNoVerbose = 500,
oHomedir, oHomedir,
oHex oHex,
oNoExtConnect
}; };
@ -58,6 +60,9 @@ static ARGPARSE_OPTS opts[] =
{ oQuiet, "quiet", 0, N_("quiet") }, { oQuiet, "quiet", 0, N_("quiet") },
{ oHex, "hex", 0, N_("print data out hex encoded") }, { oHex, "hex", 0, N_("print data out hex encoded") },
{ oRawSocket, "raw-socket", 2, N_("|NAME|connect to Assuan socket NAME")}, { 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 */ /* hidden options */
{ oNoVerbose, "no-verbose", 0, "@"}, { oNoVerbose, "no-verbose", 0, "@"},
@ -74,6 +79,8 @@ struct
const char *homedir; /* Configuration directory name */ const char *homedir; /* Configuration directory name */
int hex; /* Print data lines in hex format. */ int hex; /* Print data lines in hex format. */
const char *raw_socket; /* Name of socket to connect in raw mode. */ 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; } 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. */ /* gpg-connect-agent's entry point. */
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
ARGPARSE_ARGS pargs; ARGPARSE_ARGS pargs;
const char *fname;
int no_more_options = 0; int no_more_options = 0;
assuan_context_t ctx; assuan_context_t ctx;
char *line, *p; char *line, *p;
@ -229,6 +291,7 @@ main (int argc, char **argv)
i18n_init(); i18n_init();
opt.homedir = default_homedir (); opt.homedir = default_homedir ();
opt.connect_flags = 1; /* Use extended connect mode. */
/* Parse the command line. */ /* Parse the command line. */
pargs.argc = &argc; pargs.argc = &argc;
@ -244,6 +307,8 @@ main (int argc, char **argv)
case oHomedir: opt.homedir = pargs.r.ret_str; break; case oHomedir: opt.homedir = pargs.r.ret_str; break;
case oHex: opt.hex = 1; break; case oHex: opt.hex = 1; break;
case oRawSocket: opt.raw_socket = pargs.r.ret_str; 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; default: pargs.err = 2; break;
} }
@ -251,12 +316,48 @@ main (int argc, char **argv)
if (log_get_errorcount (0)) if (log_get_errorcount (0))
exit (2); 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) if (rc)
{ {
log_error ("can't connect to socket `%s': %s\n", log_error ("can't connect to socket `%s': %s\n",
@ -325,18 +426,31 @@ main (int argc, char **argv)
{ {
puts (p); 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")) else if (!strcmp (cmd, "help"))
{ {
puts ("Available commands:\n" puts (
"/echo ARGS Echo ARGS.\n" "Available commands:\n"
"/definqfile NAME FILE\n" "/echo ARGS Echo ARGS.\n"
" Use content of FILE for inquiries with NAME.\n" "/definqfile NAME FILE\n"
" NAME may be \"*\" to match any inquiry.\n" " Use content of FILE for inquiries with NAME.\n"
"/definqprog NAME PGM\n" " NAME may be \"*\" to match any inquiry.\n"
" Run PGM for inquiries matching NAME and pass the\n" "/definqprog NAME PGM\n"
" entire line to it as arguments.\n" " Run PGM for inquiries matching NAME and pass the\n"
"/showdef Print all definitions.\n" " entire line to it as arguments.\n"
"/cleardef Delete all definitions.\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."); "/help Print this help.");
} }
else else
@ -352,7 +466,7 @@ main (int argc, char **argv)
continue; continue;
} }
if (*line == '#' || !*line) 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); rc = read_and_print_response (ctx);
if (rc) if (rc)
@ -471,6 +585,12 @@ read_and_print_response (assuan_context_t ctx)
rc = assuan_read_line (ctx, &line, &linelen); rc = assuan_read_line (ctx, &line, &linelen);
if (rc) if (rc)
return rc; return rc;
if (opt.verbose > 1 && *line == '#')
{
fwrite (line, linelen, 1, stdout);
putchar ('\n');
}
} }
while (*line == '#' || !linelen); while (*line == '#' || !linelen);