1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

Revamped the keyring code

This commit is contained in:
Werner Koch 2001-09-06 17:10:00 +00:00
parent 3f465d5d7a
commit ed17c7afd0
45 changed files with 2464 additions and 2764 deletions

View File

@ -1,3 +1,7 @@
2001-09-03 Werner Koch <wk@gnupg.org>
* configure.ac: Removed GDBM tests.
2001-08-23 Werner Koch <wk@gnupg.org>
* configure.in (AC_FUNC_FSEEKO): Add.

View File

@ -102,6 +102,11 @@ Specific problems on some machines
not build. In this case try to run configure using:
CFLAGS="-g -O2 -mcpu=powerpc" ./configure
* Compaq C V6.2 for alpha:
You may want to use the option "-msg-disable ptrmismatch1"
to get rid of the sign/unsigned char mismatch warnings.
The Random Device

4
NEWS
View File

@ -33,6 +33,10 @@
UID, encoded using %XX escaping (but with spaces left as spaces,
so that it should not break too much)
* Support for GDBM based keyrings has been removed.
* The entire keyring management has been revamped.
Noteworthy changes in version 1.0.6 (2001-05-29)
------------------------------------------------

4
TODO
View File

@ -73,11 +73,11 @@
* Concatenated encryption messages don't work corectly - only the
first one is processed.
* Add status message for reasons why a key was not selected.
* Add option to put the list of recipients (from the encryption
layer) into the signatures notation data.
* Allow to update key signatyres, add status that a key is already signed.
Scheduled for 1.1
-----------------
* export by user-IDs does only export the first matching name which leads

View File

@ -1,3 +1,7 @@
2001-09-06 Werner Koch <wk@gnupg.org>
* genkey1024.test: Simplified by using a parameter file.
2001-05-30 Werner Koch <wk@gnupg.org>
* multisig.test (IFS): Reset IFS just before the test.

View File

@ -2,99 +2,25 @@
. $srcdir/defs.inc || exit 3
if (expect -v) < /dev/null > /dev/null 2>&1 ; then
:
else
echo "\"expect\" needed but not found - test skipped"
exit 0
fi
LANG=
LANGUAGE=
expect - <<EOF >/dev/null
#set timeout -1
set timeout 8
match_max 100000
spawn ../g10/gpg --no-batch --quick-random --homedir . --gen-key
expect {
-exact "Please select what kind of key you want:\r
(1) DSA and ElGamal (default)\r
(2) DSA (sign only)\r
(4) ElGamal (sign and encrypt)\r
Your selection? " { send -- "1\r" }
timeout { exit 1 } }
expect {
-exact "1\r
\r \rDSA keypair will have 1024 bits.\r
About to generate a new ELG-E keypair.\r
minimum keysize is 768 bits\r
default keysize is 1024 bits\r
highest suggested keysize is 2048 bits\r
What keysize do you want? (1024) " { send -- "\r" }
timeout { exit 1 } }
expect {
-exact "\r
\r \rRequested keysize is 1024 bits\r
Please specify how long the key should be valid.\r
0 = key does not expire\r
<n> = key expires in n days\r
<n>w = key expires in n weeks\r
<n>m = key expires in n months\r
<n>y = key expires in n years\r
Key is valid for? (0) " { send -- "1\r" }
timeout { exit 1 } }
expect {
-exact "1\r
\r \rKey expires at " { }
timeout { exit 1 } }
expect {
-re "(.*)\r
" {}
timeout { exit 1 } }
expect {
-exact "Is this correct (y/n)? " { send -- "y\r" }
timeout { exit 1 } }
expect {
-exact "y\r
\r \r\r
You need a User-ID to identify your key; the software constructs the user id\r
from Real Name, Comment and Email Address in this form:\r
\"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\r
\r
Real name: " { send -- "Harry H.\r" }
timeout { exit 1 } }
expect {
-exact "Harry H.\r
\r \rEmail address: " { send -- "hh@ddorf.de\r" }
timeout { exit 1 } }
expect {
-exact "hh@ddorf.de\r
\r \rComment: " { send -- "a test\r" }
timeout { exit 1 } }
expect {
-exact "a test\r
\r \rYou selected this USER-ID:\r
\"Harry H. (a test) <hh@ddorf.de> (INSECURE!)\"\r
\r
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " { send -- "o\r" }
timeout { exit 1 } }
expect {
-exact "o\r
\r \rYou need a Passphrase to protect your secret key.\r
\r
Enter passphrase: " { sleep 1; send -- "abc\r" }
timeout { exit 1 } }
expect {
-ex "\r \rRepeat passphrase: " { sleep 1; send -- "abc\r" }
timeout { exit 1 } }
set timeout 600
expect {
-re "^.*\r\npublic and secret key" { exit 0 }
eof { exit 1 }
}
exit 1
../g10/gpg --quiet --batch --quick-random --homedir . --gen-key <<EOF
Key-Type: DSA
Key-Length: 1024
Subkey-Type: ELG-E
Subkey-Length: 1024
Name-Real: Harry H.
Name-Comment: test key
Name-Email: hh@@ddorf.de
Expire-Date: 1
Passphrase: abc
%commit
Key-Type: RSA
Key-Length: 1024
Key-Usage: sign,encrypt
Name-Real: Harry A.
Name-Comment: RSA test key
Name-Email: hh@@ddorf.de
Expire-Date: 2
Passphrase: abc
%commit
EOF
#*-*wedit:notab*-*

View File

@ -183,7 +183,6 @@ MPI_OPT_FLAGS=""
try_gettext=yes
try_gdbm=yes
case "${target}" in
*-*-mingw32*)
# special stuff for Windoze NT
@ -201,7 +200,6 @@ case "${target}" in
MingW32 systems and these systems lack Posix functions,
we use a simplified version of gettext])
try_gettext="no"
try_gdbm="no"
;;
i?86-emx-os2 | i?86-*-os2*emx )
# OS/2 with the EMX environment
@ -209,7 +207,6 @@ case "${target}" in
AC_DEFINE(HAVE_DRIVE_LETTERS)
AC_DEFINE(HAVE_DOSISH_SYSTEM)
try_gettext="no"
try_gdbm="no"
;;
i?86-*-msdosdjgpp*)
@ -218,7 +215,6 @@ case "${target}" in
AC_DEFINE(HAVE_DRIVE_LETTERS)
AC_DEFINE(HAVE_DOSISH_SYSTEM)
try_gettext="no"
try_gdbm="no"
;;
*-*-freebsd*)
@ -363,41 +359,6 @@ AC_SUBST(USE_INCLUDED_LIBINTL)
AC_SUBST(BUILD_INCLUDED_LIBINTL)
fi
dnl
dnl There are lot of misconfigured systems. We include
dnl gdbm support only if the lib and the header is installed.
dnl
if test "$try_gdbm" = yes; then
AC_CHECK_HEADERS(gdbm.h)
if test "$ac_cv_header_gdbm_h" = yes ; then
AC_CHECK_LIB(gdbm,gdbm_firstkey)
fi
fi
dnl This old test is here just for reference tin case it fails:
dnl
dnl Solaris needs -lsocket and -lnsl. Unisys system includes
dnl gethostbyname in libsocket but needs libnsl for socket.
dnl The test does not workfor all system, so some are hardcoded here.
dnl case "${target}" in
dnl i386-univel-sysv4*)
dnl LIBS="$LIBS -lsocket -lnsl"
dnl ;;
dnl *)
dnl AC_CHECK_LIB(nsl, gethostbyname)
dnl AC_CHECK_LIB(socket, socket, ac_need_libsocket=1, ac_try_nsl=1)
dnl if test x$ac_need_libsocket = x1; then
dnl LIBS="$LIBS -lsocket"
dnl fi
dnl if test x$ac_try_nsl = x1; then
dnl AC_CHECK_LIB(nsl, gethostbyname, ac_need_libnsl=1)
dnl if test x$ac_need_libnsl = x1
dnl then
dnl LIBS="$LIBS -lnsl"
dnl fi
dnl fi
dnl ;;
dnl esac
AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, gethostbyname))
AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt))

View File

@ -1,3 +1,7 @@
2001-09-03 Werner Koch <wk@gnupg.org>
* gpg.sgml, gpgv.sgml: Removed GDBM stuff.
2001-08-29 Werner Koch <wk@gnupg.org>
* faq.raw: Described how to delete a secret key w/o a public key

View File

@ -283,6 +283,10 @@ more arguments in future versions.
END_STREAM
Issued by pipemode.
INV_RECP <reason> <requested_recipient>
Issued for each unusable recipient. The only reason code
currently defined is 0 for "No specific reason given".
Key generation
==============

View File

@ -839,8 +839,6 @@ does not contain a slash, it is assumed to be in the
home-directory ("~/.gnupg" if --homedir is not used).
The filename may be prefixed with a scheme:</para>
<para>"gnupg-ring:" is the default one.</para>
<para>"gnupg-gdbm:" may be used for a GDBM ring. Note that GDBM
is experimental and likely to be removed in future versions.</para>
<para>It might make sense to use it together with --no-default-keyring.
</para></listitem></varlistentry>

View File

@ -119,8 +119,6 @@ does not contain a slash, it is assumed to be in the
home-directory ("~/.gnupg" if --homedir is not used).
The filename may be prefixed with a scheme:</para>
<para>"gnupg-ring:" is the default one.</para>
<para>"gnupg-gdbm:" may be used for a GDBM ring. Note that GDBM
is experimental and likely to be removed in future versions.</para>
<para>It might make sense to use it together with --no-default-keyring.
</para></listitem></varlistentry>

View File

@ -1,3 +1,57 @@
2001-09-06 Werner Koch <wk@gnupg.org>
* getkey.c (fixup_uidnode): Features flag is now a bit vector.
* keygen.c (add_feature_mdc): Ditto.
Revamped the entire key I/O code to be prepared for other ways of
key storages and to get rid of the existing shit. GDBM support has
gone.
* keydb.c: New
* keyring.c, keyring.h: New.
* ringedit.c: Removed. Moved some stuff to keyring.c
* getkey.c: Changed everything related to the key retrieving
functions which are now using the keydb_ functions.
(prepare_search, word_match_chars, word_match)
(prepare_word_match, compare_name): Moved to keyring.c
(get_pubkey_byname): Removed ctx arg and add ret_kdbhd
arg. Changed all callers.
(key_byname): Use get_pubkey_end to release the context and take
new ret_kbdhd arg. Changed all callers.
(classify_user_id2): Fill the 16 byte fingerprint up with 4 null
bytes not with zero bytes of value 4, tsss.
* import.c (import_one): Updated to use the new keydb interface.
(import_secret_one): Ditto.
(import_revoke_cert): Ditto.
* delkey.c (do_delete_key): Ditto.
* keyedit.c (keyedit_menu): Ditto.
(get_keyblock_byname): Removed.
* revoke.c (gen_revoke): Ditto.
* export.c (do_export_stream): Ditto.
* trustdb.c (update_trustdb): Ditto.
* g10.c, gpgv.c (main): Renamed add_keyblock_resource to
keydb_add_resource.
* Makefile.am: Added and removed files.
* keydb.h: Moved KBNODE typedef and MAX_FINGERPRINT_LEN to
* global.h: this new header.
2001-09-03 Werner Koch <wk@gnupg.org>
* passphrase.c (agent_get_passphrase): Changed nread to size_t.
(passphrase_clear_cache): Ditto.
* keyid.c (mk_datestr): Avoid trigraphs.
(fingerprint_from_pk): Cache the keyid in the pk.
* options.h: Add opt.with_fingerprint so that we know whether the
corresponding options was used.
* g10.c (main): Set it here.
* pkclist.c (check_signatures_trust): Always print fingerprint
when this option is used. Mixed a minor memory leak.
* status.c, status.h: New status INV_RECP.
* pkclist.c (build_pk_list): Issue this status.
2001-08-31 Werner Koch <wk@gnupg.org>
* parse-packet.c (parse_key,parse_pubkeyenc)

View File

@ -28,14 +28,15 @@ needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a
bin_PROGRAMS = gpg gpgv
common_source = \
global.h \
build-packet.c \
compress.c \
filter.h \
free-packet.c \
getkey.c \
ringedit.c \
keydb.c keydb.h \
keyring.c keyring.h \
seskey.c \
keydb.h \
kbnode.c \
main.h \
mainproc.c \

View File

@ -52,37 +52,35 @@ do_delete_key( const char *username, int secret, int *r_sec_avail )
int rc = 0;
KBNODE keyblock = NULL;
KBNODE node;
KBPOS kbpos;
KEYDB_HANDLE hd = keydb_new (secret);
PKT_public_key *pk = NULL;
PKT_secret_key *sk = NULL;
u32 keyid[2];
int okay=0;
int yes;
KEYDB_SEARCH_DESC desc;
*r_sec_avail = 0;
/* search the userid */
if (secret
&& classify_user_id (username, keyid, NULL, NULL, NULL) == 11) {
/* if the user supplied a long keyID we use the direct search
methods which allows us to delete a key if the
corresponding secret key is missing */
rc = find_secret_keyblock_direct (&kbpos, keyid);
}
else if (secret)
rc = find_secret_keyblock_byname (&kbpos, username);
else
rc = find_keyblock_byname (&kbpos, username);
if( rc ) {
log_error(_("%s: user not found\n"), username );
/* search the userid */
memset (&desc, 0, sizeof desc);
desc.mode = classify_user_id (username,
desc.u.kid,
desc.u.fpr,
&desc.u.name,
NULL);
rc = desc.mode? keydb_search (hd, &desc, 1):G10ERR_INV_USER_ID;
if (rc) {
log_error (_("key `%s' not found: %s\n"), username, g10_errstr (rc));
write_status_text( STATUS_DELETE_PROBLEM, "1" );
goto leave;
}
/* read the keyblock */
rc = read_keyblock( &kbpos, &keyblock );
if( rc ) {
log_error("%s: read problem: %s\n", username, g10_errstr(rc) );
rc = keydb_get_keyblock (hd, &keyblock );
if (rc) {
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
goto leave;
}
@ -159,15 +157,16 @@ do_delete_key( const char *username, int secret, int *r_sec_avail )
if( okay ) {
rc = delete_keyblock( &kbpos );
if( rc ) {
log_error("delete_keyblock failed: %s\n", g10_errstr(rc) );
rc = keydb_delete_keyblock (hd);
if (rc) {
log_error (_("deleting keyblock failed: %s\n"), g10_errstr(rc) );
goto leave;
}
}
leave:
release_kbnode( keyblock );
keydb_release (hd);
release_kbnode (keyblock);
return rc;
}

View File

@ -112,58 +112,56 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
PACKET pkt;
KBNODE keyblock = NULL;
KBNODE kbctx, node;
KBPOS kbpos;
KEYDB_HANDLE kdbhd;
STRLIST sl;
int all = !users;
int all_first = 1;
*any = 0;
memset( &zfx, 0, sizeof zfx);
init_packet( &pkt );
kdbhd = keydb_new (secret);
if( opt.compress_keys && opt.compress )
iobuf_push_filter( out, compress_filter, &zfx );
if( all ) {
rc = enum_keyblocks( secret?5:0, &kbpos, &keyblock );
if( rc ) {
if( rc != -1 )
log_error("enum_keyblocks(open) failed: %s\n", g10_errstr(rc) );
goto leave;
}
all = 2;
}
/* use the correct sequence. strlist_last,prev do work correctly with
* NULL pointers :-) */
for( sl=strlist_last(users); sl || all ; sl=strlist_prev( users, sl )) {
if( all ) { /* get the next user */
rc = enum_keyblocks( 1, &kbpos, &keyblock );
rc = all_first ? keydb_search_first (kdbhd)
: keydb_search_next (kdbhd);
all_first = 0;
if( rc == -1 ) /* EOF */
break;
if( rc ) {
log_error("enum_keyblocks(read) failed: %s\n", g10_errstr(rc));
log_error ("error searching key: %s\n", g10_errstr(rc));
break;
}
}
else {
/* search the userid */
rc = secret? find_secret_keyblock_byname( &kbpos, sl->d )
: find_keyblock_byname( &kbpos, sl->d );
KEYDB_SEARCH_DESC desc;
memset (&desc, 0, sizeof desc);
desc.mode = classify_user_id (sl->d, desc.u.kid, desc.u.fpr,
&desc.u.name, NULL);
rc = desc.mode? keydb_search (kdbhd, &desc, 1):G10ERR_INV_USER_ID;
if( rc ) {
log_error(_("%s: user not found: %s\n"), sl->d, g10_errstr(rc));
log_error (_("key `%s' not found: %s\n"),
sl->d, g10_errstr (rc));
rc = 0;
continue;
}
/* read the keyblock */
rc = read_keyblock( &kbpos, &keyblock );
}
/* read the keyblock */
rc = keydb_get_keyblock (kdbhd, &keyblock );
if( rc ) {
log_error(_("certificate read problem: %s\n"), g10_errstr(rc));
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
goto leave;
}
/* do not export keys which are incompatible with rfc2440 */
if( onlyrfc && (node = find_kbnode( keyblock, PKT_PUBLIC_KEY )) ) {
PKT_public_key *pk = node->pkt->pkt.public_key;
@ -229,8 +227,7 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
rc = 0;
leave:
if( all == 2 )
enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
keydb_release (kdbhd);
release_kbnode( keyblock );
if( !*any )
log_info(_("WARNING: nothing exported\n"));

View File

@ -886,7 +886,8 @@ main( int argc, char **argv )
break;
#endif /* __riscos__ */
case oWithFingerprint:
with_fpr=1; /*fall thru*/
opt.with_fingerprint = 1;
with_fpr=1; /*fall thru*/
case oFingerprint: opt.fingerprint++; break;
case oSecretKeyring: append_to_strlist( &sec_nrings, pargs.r.ret_str); break;
case oOptions:
@ -1225,13 +1226,13 @@ main( int argc, char **argv )
&& !(cmd == aKMode && argc == 2 ) ) {
if( !sec_nrings || default_keyring ) /* add default secret rings */
add_keyblock_resource("secring" EXTSEP_S "gpg", 0, 1);
keydb_add_resource ("secring" EXTSEP_S "gpg", 0, 1);
for(sl = sec_nrings; sl; sl = sl->next )
add_keyblock_resource( sl->d, 0, 1 );
keydb_add_resource ( sl->d, 0, 1 );
if( !nrings || default_keyring ) /* add default ring */
add_keyblock_resource("pubring" EXTSEP_S "gpg", 0, 0);
keydb_add_resource ("pubring" EXTSEP_S "gpg", 0, 0);
for(sl = nrings; sl; sl = sl->next )
add_keyblock_resource( sl->d, 0, 0 );
keydb_add_resource ( sl->d, 0, 0 );
}
FREE_STRLIST(nrings);
FREE_STRLIST(sec_nrings);
@ -1445,7 +1446,7 @@ main( int argc, char **argv )
else {
/* add keyring (default keyrings are not registered in this
* special case */
add_keyblock_resource( argv[1], 0, 0 );
keydb_add_resource( argv[1], 0, 0 );
sl = NULL;
if (**argv)
add_to_strlist2( &sl, *argv, utf8_strings );

File diff suppressed because it is too large Load Diff

29
g10/global.h Normal file
View File

@ -0,0 +1,29 @@
/* global.h - Local typedefs and constants
* Copyright (C) 2001 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
*/
#ifndef GPG_GLOBAL_H
#define GPG_GLOBAL_H
#define MAX_FINGERPRINT_LEN 20
typedef struct kbnode_struct *KBNODE;
typedef struct keydb_search_desc KEYDB_SEARCH_DESC;
#endif /*GPG_GLOBAL_H*/

View File

@ -189,9 +189,9 @@ main( int argc, char **argv )
set_packet_list_mode(1);
if( !nrings ) /* no keyring given: use default one */
add_keyblock_resource("trustedkeys" EXTSEP_S "gpg", 0, 0);
keydb_add_resource ("trustedkeys" EXTSEP_S "gpg", 0, 0);
for(sl = nrings; sl; sl = sl->next )
add_keyblock_resource( sl->d, 0, 0 );
keydb_add_resource (sl->d, 0, 0 );
FREE_STRLIST(nrings);

View File

@ -379,7 +379,6 @@ import_one( const char *fname, KBNODE keyblock, int fast )
PKT_public_key *pk_orig;
KBNODE node, uidnode;
KBNODE keyblock_orig = NULL;
KBPOS kbpos;
u32 keyid[2];
int rc = 0;
int new_key = 0;
@ -443,21 +442,20 @@ import_one( const char *fname, KBNODE keyblock, int fast )
stats.skipped_new_keys++;
}
else if( rc ) { /* insert this key */
/* get default resource */
if( get_keyblock_handle( NULL, 0, &kbpos ) ) {
log_error(_("no default public keyring\n"));
KEYDB_HANDLE hd = keydb_new (0);
rc = keydb_locate_writable (hd, NULL);
if (rc) {
log_error (_("no writable keyring found: %s\n"), g10_errstr (rc));
return G10ERR_GENERAL;
}
if( opt.verbose > 1 )
log_info( _("writing to `%s'\n"),
keyblock_resource_name(&kbpos) );
if( (rc=lock_keyblock( &kbpos )) )
log_error(_("can't lock keyring `%s': %s\n"),
keyblock_resource_name(&kbpos), g10_errstr(rc) );
else if( (rc=insert_keyblock( &kbpos, keyblock )) )
log_error( _("error writing keyring `%s': %s\n"),
keyblock_resource_name(&kbpos), g10_errstr(rc) );
unlock_keyblock( &kbpos );
log_info (_("writing to `%s'\n"), keydb_get_resource_name (hd) );
rc = keydb_insert_keyblock (hd, keyblock );
if (rc)
log_error (_("error writing keyring `%s': %s\n"),
keydb_get_resource_name (hd), g10_errstr(rc));
keydb_release (hd);
/* we are ready */
if( !opt.quiet )
log_info( _("key %08lX: public key imported\n"), (ulong)keyid[1]);
@ -472,8 +470,10 @@ import_one( const char *fname, KBNODE keyblock, int fast )
new_key = 1;
}
else { /* merge */
KEYDB_HANDLE hd;
int n_uids, n_sigs, n_subk;
/* Compare the original against the new key; just to be sure nothing
* weird is going on */
if( cmp_public_keys( pk_orig, pk ) ) {
@ -484,16 +484,27 @@ import_one( const char *fname, KBNODE keyblock, int fast )
}
/* now read the original keyblock */
rc = find_keyblock_bypk( &kbpos, pk_orig );
hd = keydb_new (0);
{
byte afp[MAX_FINGERPRINT_LEN];
size_t an;
fingerprint_from_pk (pk_orig, afp, &an);
while (an < MAX_FINGERPRINT_LEN)
afp[an++] = 0;
rc = keydb_search_fpr (hd, afp);
}
if( rc ) {
log_error( _("key %08lX: can't locate original keyblock: %s\n"),
log_error (_("key %08lX: can't locate original keyblock: %s\n"),
(ulong)keyid[1], g10_errstr(rc));
keydb_release (hd);
goto leave;
}
rc = read_keyblock( &kbpos, &keyblock_orig );
if( rc ) {
log_error( _("key %08lX: can't read original keyblock: %s\n"),
rc = keydb_get_keyblock (hd, &keyblock_orig );
if (rc) {
log_error (_("key %08lX: can't read original keyblock: %s\n"),
(ulong)keyid[1], g10_errstr(rc));
keydb_release (hd);
goto leave;
}
@ -504,18 +515,18 @@ import_one( const char *fname, KBNODE keyblock, int fast )
n_uids = n_sigs = n_subk = 0;
rc = merge_blocks( fname, keyblock_orig, keyblock,
keyid, &n_uids, &n_sigs, &n_subk );
if( rc )
if( rc ) {
keydb_release (hd);
goto leave;
}
if( n_uids || n_sigs || n_subk ) {
mod_key = 1;
/* keyblock_orig has been updated; write */
if( (rc=lock_keyblock( &kbpos )) )
log_error( _("can't lock keyring `%s': %s\n"),
keyblock_resource_name(&kbpos), g10_errstr(rc) );
else if( (rc=update_keyblock( &kbpos, keyblock_orig )) )
log_error( _("error writing keyring `%s': %s\n"),
keyblock_resource_name(&kbpos), g10_errstr(rc) );
unlock_keyblock( &kbpos );
rc = keydb_update_keyblock (hd, keyblock_orig);
if (rc)
log_error (_("error writing keyring `%s': %s\n"),
keydb_get_resource_name (hd), g10_errstr(rc) );
keydb_release (hd); hd = NULL;
/* we are ready */
if( !opt.quiet ) {
if( n_uids == 1 )
@ -582,7 +593,6 @@ import_secret_one( const char *fname, KBNODE keyblock, int allow )
{
PKT_secret_key *sk;
KBNODE node, uidnode;
KBPOS kbpos;
u32 keyid[2];
int rc = 0;
@ -623,18 +633,20 @@ import_secret_one( const char *fname, KBNODE keyblock, int allow )
/* do we have this key already in one of our secrings ? */
rc = seckey_available( keyid );
if( rc == G10ERR_NO_SECKEY && !opt.merge_only ) { /* simply insert this key */
KEYDB_HANDLE hd = keydb_new (1);
/* get default resource */
if( get_keyblock_handle( NULL, 1, &kbpos ) ) {
log_error("no default secret keyring\n");
rc = keydb_locate_writable (hd, NULL);
if (rc) {
log_error (_("no default secret keyring: %s\n"), g10_errstr (rc));
keydb_release (hd);
return G10ERR_GENERAL;
}
if( (rc=lock_keyblock( &kbpos )) )
log_error( _("can't lock keyring `%s': %s\n"),
keyblock_resource_name(&kbpos), g10_errstr(rc) );
else if( (rc=insert_keyblock( &kbpos, keyblock )) )
log_error( _("error writing keyring `%s': %s\n"),
keyblock_resource_name(&kbpos), g10_errstr(rc) );
unlock_keyblock( &kbpos );
rc = keydb_insert_keyblock (hd, keyblock );
if (rc)
log_error (_("error writing keyring `%s': %s\n"),
keydb_get_resource_name (hd), g10_errstr(rc) );
keydb_release (hd);
/* we are ready */
if( !opt.quiet )
log_info( _("key %08lX: secret key imported\n"), (ulong)keyid[1]);
@ -661,7 +673,7 @@ import_revoke_cert( const char *fname, KBNODE node )
{
PKT_public_key *pk=NULL;
KBNODE onode, keyblock = NULL;
KBPOS kbpos;
KEYDB_HANDLE hd = NULL;
u32 keyid[2];
int rc = 0;
@ -687,16 +699,25 @@ import_revoke_cert( const char *fname, KBNODE node )
}
/* read the original keyblock */
rc = find_keyblock_bypk( &kbpos, pk );
if( rc ) {
log_error( _("key %08lX: can't locate original keyblock: %s\n"),
(ulong)keyid[1], g10_errstr(rc));
hd = keydb_new (0);
{
byte afp[MAX_FINGERPRINT_LEN];
size_t an;
fingerprint_from_pk (pk, afp, &an);
while (an < MAX_FINGERPRINT_LEN)
afp[an++] = 0;
rc = keydb_search_fpr (hd, afp);
}
if (rc) {
log_error (_("key %08lX: can't locate original keyblock: %s\n"),
(ulong)keyid[1], g10_errstr(rc));
goto leave;
}
rc = read_keyblock( &kbpos, &keyblock );
if( rc ) {
log_error( _("key %08lX: can't read original keyblock: %s\n"),
(ulong)keyid[1], g10_errstr(rc));
rc = keydb_get_keyblock (hd, &keyblock );
if (rc) {
log_error (_("key %08lX: can't read original keyblock: %s\n"),
(ulong)keyid[1], g10_errstr(rc));
goto leave;
}
@ -729,13 +750,11 @@ import_revoke_cert( const char *fname, KBNODE node )
insert_kbnode( keyblock, clone_kbnode(node), 0 );
/* and write the keyblock back */
if( (rc=lock_keyblock( &kbpos )) )
log_error( _("can't lock keyring `%s': %s\n"),
keyblock_resource_name(&kbpos), g10_errstr(rc) );
else if( (rc=update_keyblock( &kbpos, keyblock )) )
log_error( _("error writing keyring `%s': %s\n"),
keyblock_resource_name(&kbpos), g10_errstr(rc) );
unlock_keyblock( &kbpos );
rc = keydb_update_keyblock (hd, keyblock );
if (rc)
log_error (_("error writing keyring `%s': %s\n"),
keydb_get_resource_name (hd), g10_errstr(rc) );
keydb_release (hd); hd = NULL;
/* we are ready */
if( !opt.quiet )
log_info( _("key %08lX: revocation certificate imported\n"),
@ -752,6 +771,7 @@ import_revoke_cert( const char *fname, KBNODE node )
}
leave:
keydb_release (hd);
release_kbnode( keyblock );
free_public_key( pk );
return rc;

623
g10/keydb.c Normal file
View File

@ -0,0 +1,623 @@
/* keydb.c - key database dispatcher
* Copyright (C) 2001 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
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "util.h"
#include "options.h"
#include "main.h" /*try_make_homedir ()*/
#include "packet.h"
#include "keyring.h"
#include "keydb.h"
#include "i18n.h"
static int active_handles;
typedef enum {
KEYDB_RESOURCE_TYPE_NONE = 0,
KEYDB_RESOURCE_TYPE_KEYRING
} KeydbResourceType;
#define MAX_KEYDB_RESOURCES 1
struct resource_item {
KeydbResourceType type;
union {
KEYRING_HANDLE kr;
} u;
};
struct keydb_handle {
int locked;
int found;
int current;
struct resource_item active[MAX_KEYDB_RESOURCES];
};
static int lock_all (KEYDB_HANDLE hd);
static void unlock_all (KEYDB_HANDLE hd);
/*
* Register a resource (which currently may only be a keyring file).
* The first keyring which is added by this function is
* created if it does not exist.
* Note: this function may be called before secure memory is
* available.
*/
int
keydb_add_resource (const char *url, int force, int secret)
{
static int any_secret, any_public;
const char *resname = url;
IOBUF iobuf = NULL;
char *filename = NULL;
int rc = 0;
KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
const char *created_fname = NULL;
/* Do we have an URL?
* gnupg-ring:filename := this is a plain keyring
* filename := See what is is, but create as plain keyring.
*/
if (strlen (resname) > 11) {
if (!strncmp( resname, "gnupg-ring:", 11) ) {
rt = KEYDB_RESOURCE_TYPE_KEYRING;
resname += 11;
}
#if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
else if (strchr (resname, ':')) {
log_error ("invalid key resource URL `%s'\n", url );
rc = G10ERR_GENERAL;
goto leave;
}
#endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
}
if (*resname != DIRSEP_C ) { /* do tilde expansion etc */
if (strchr(resname, DIRSEP_C) )
filename = make_filename (resname, NULL);
else
filename = make_filename (opt.homedir, resname, NULL);
}
else
filename = m_strdup (resname);
if (!force)
force = secret? !any_secret : !any_public;
/* see whether we can determine the filetype */
if (rt == KEYDB_RESOURCE_TYPE_NONE) {
FILE *fp = fopen( filename, "rb" );
if (fp) {
u32 magic;
if (fread( &magic, 4, 1, fp) == 1 ) {
if (magic == 0x13579ace || magic == 0xce9a5713)
; /* GDBM magic - no more support */
else
rt = KEYDB_RESOURCE_TYPE_KEYRING;
}
else /* maybe empty: assume ring */
rt = KEYDB_RESOURCE_TYPE_KEYRING;
fclose( fp );
}
else /* no file yet: create ring */
rt = KEYDB_RESOURCE_TYPE_KEYRING;
}
switch (rt) {
case KEYDB_RESOURCE_TYPE_NONE:
log_error ("unknown type of key resource `%s'\n", url );
rc = G10ERR_GENERAL;
goto leave;
case KEYDB_RESOURCE_TYPE_KEYRING:
iobuf = iobuf_open (filename);
if (!iobuf && !force) {
rc = G10ERR_OPEN_FILE;
goto leave;
}
if (!iobuf) {
char *last_slash_in_filename;
last_slash_in_filename = strrchr (filename, DIRSEP_C);
*last_slash_in_filename = 0;
if (access(filename, F_OK)) {
/* on the first time we try to create the default homedir and
* in this case the process will be terminated, so that on the
* next invocation it can read the options file in on startup
*/
try_make_homedir (filename);
rc = G10ERR_OPEN_FILE;
*last_slash_in_filename = DIRSEP_C;
goto leave;
}
*last_slash_in_filename = DIRSEP_C;
iobuf = iobuf_create (filename);
if (!iobuf) {
log_error ( _("error creating keyring `%s': %s\n"),
filename, strerror(errno));
rc = G10ERR_OPEN_FILE;
goto leave;
}
else {
#ifndef HAVE_DOSISH_SYSTEM
if (secret && !opt.preserve_permissions) {
if (chmod (filename, S_IRUSR | S_IWUSR) ) {
log_error (_("changing permission of "
" `%s' failed: %s\n"),
filename, strerror(errno) );
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
#endif
if (!opt.quiet)
log_info (_("keyring `%s' created\n"), filename);
created_fname = filename;
}
}
iobuf_close (iobuf);
iobuf = NULL;
if (created_fname) /* must invalidate that ugly cache */
iobuf_ioctl (NULL, 2, 0, (char*)created_fname);
keyring_register_filename (filename, secret);
break;
default:
log_error ("resource type of `%s' not supported\n", url);
rc = G10ERR_GENERAL;
goto leave;
}
/* fixme: check directory permissions and print a warning */
leave:
if (rc)
log_error ("keyblock resource `%s': %s\n", filename, g10_errstr(rc));
else if (secret)
any_secret = 1;
else
any_public = 1;
m_free (filename);
return rc;
}
KEYDB_HANDLE
keydb_new (int secret)
{
KEYDB_HANDLE hd;
int i=0;
hd = m_alloc_clear (sizeof *hd);
hd->found = -1;
hd->active[i].type = KEYDB_RESOURCE_TYPE_KEYRING;
hd->active[i].u.kr = keyring_new (secret);
if (!hd->active[i].u.kr) {
m_free (hd);
return NULL;
}
i++;
assert (i <= MAX_KEYDB_RESOURCES);
active_handles++;
return hd;
}
void
keydb_release (KEYDB_HANDLE hd)
{
int i;
if (!hd)
return;
assert (active_handles > 0);
active_handles--;
unlock_all (hd);
for (i=0; i < MAX_KEYDB_RESOURCES; i++) {
switch (hd->active[i].type) {
case KEYDB_RESOURCE_TYPE_NONE:
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
keyring_release (hd->active[i].u.kr);
break;
}
}
m_free (hd);
}
/*
* Return the name of the current resource. This is function first
* looks for the last found found, then for the current search
* position, and last returns the first available resource. The
* returned string is only valid as long as the handle exists. This
* function does only return NULL if no handle is specified, in all
* other error cases an empty string is returned.
*/
const char *
keydb_get_resource_name (KEYDB_HANDLE hd)
{
int idx;
const char *s = NULL;
if (!hd)
return NULL;
if ( hd->found >= 0 && hd->found < MAX_KEYDB_RESOURCES)
idx = hd->found;
else if ( hd->current >= 0 && hd->current < MAX_KEYDB_RESOURCES)
idx = hd->current;
else
idx = 0;
switch (hd->active[idx].type) {
case KEYDB_RESOURCE_TYPE_NONE:
s = NULL;
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
s = keyring_get_resource_name (hd->active[idx].u.kr);
break;
}
return s? s: "";
}
static int
lock_all (KEYDB_HANDLE hd)
{
int i, rc = 0;
for (i=0; !rc && i < MAX_KEYDB_RESOURCES; i++) {
switch (hd->active[i].type) {
case KEYDB_RESOURCE_TYPE_NONE:
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_lock (hd->active[i].u.kr, 1);
break;
}
}
if (rc) {
/* revert the alreadt set locks */
for (i--; i >= 0; i--) {
switch (hd->active[i].type) {
case KEYDB_RESOURCE_TYPE_NONE:
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
keyring_lock (hd->active[i].u.kr, 0);
break;
}
}
}
else
hd->locked = 1;
return rc;
}
static void
unlock_all (KEYDB_HANDLE hd)
{
int i;
if (!hd->locked)
return;
for (i=MAX_KEYDB_RESOURCES-1; i >= 0; i--) {
switch (hd->active[i].type) {
case KEYDB_RESOURCE_TYPE_NONE:
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
keyring_lock (hd->active[i].u.kr, 0);
break;
}
}
hd->locked = 0;
}
/*
* Return the last found keyring. Caller must free it.
* The returned keyblock has the kbode flag bit 0 set for the node with
* the public key used to locate the keyblock or flag bit 1 set for
* the user ID node.
*/
int
keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
{
int rc = 0;
if (!hd)
return G10ERR_INV_ARG;
if ( hd->found < 0 || hd->found >= MAX_KEYDB_RESOURCES)
return -1; /* nothing found */
switch (hd->active[hd->found].type) {
case KEYDB_RESOURCE_TYPE_NONE:
rc = G10ERR_GENERAL; /* oops */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
break;
}
return rc;
}
/*
* update the current keyblock with KB
*/
int
keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
{
int rc = 0;
if (!hd)
return G10ERR_INV_ARG;
if ( hd->found < 0 || hd->found >= MAX_KEYDB_RESOURCES)
return -1; /* nothing found */
if( opt.dry_run )
return 0;
rc = lock_all (hd);
if (rc)
return rc;
switch (hd->active[hd->found].type) {
case KEYDB_RESOURCE_TYPE_NONE:
rc = G10ERR_GENERAL; /* oops */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_update_keyblock (hd->active[hd->found].u.kr, kb);
break;
}
unlock_all (hd);
return rc;
}
/*
* Insert a new KB into one of the resources.
*/
int
keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
{
int rc = -1;
int idx;
if (!hd)
return G10ERR_INV_ARG;
if( opt.dry_run )
return 0;
if ( hd->found >= 0 && hd->found < MAX_KEYDB_RESOURCES)
idx = hd->found;
else if ( hd->current >= 0 && hd->current < MAX_KEYDB_RESOURCES)
idx = hd->current;
else
return G10ERR_GENERAL;
rc = lock_all (hd);
if (rc)
return rc;
switch (hd->active[idx].type) {
case KEYDB_RESOURCE_TYPE_NONE:
rc = G10ERR_GENERAL; /* oops */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb);
break;
}
unlock_all (hd);
return rc;
}
/*
* The current keyblock will be deleted.
*/
int
keydb_delete_keyblock (KEYDB_HANDLE hd)
{
int rc = -1;
if (!hd)
return G10ERR_INV_ARG;
if ( hd->found < 0 || hd->found >= MAX_KEYDB_RESOURCES)
return -1; /* nothing found */
if( opt.dry_run )
return 0;
rc = lock_all (hd);
if (rc)
return rc;
switch (hd->active[hd->found].type) {
case KEYDB_RESOURCE_TYPE_NONE:
rc = G10ERR_GENERAL; /* oops */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_delete_keyblock (hd->active[hd->found].u.kr);
break;
}
unlock_all (hd);
return rc;
}
/*
* Locate the default writable key resource, so that the next
* operation (which is only releavnt for inserts) will be onde on this
* resource.
*/
int
keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
{
int rc;
if (!hd)
return G10ERR_INV_ARG;
rc = keydb_search_reset (hd);
if (!rc) {
/* fixme: set forward to a writable one */
}
return rc;
}
/*
* Start the next search on this handle right at the beginning
*/
int
keydb_search_reset (KEYDB_HANDLE hd)
{
int i, rc = 0;
if (!hd)
return G10ERR_INV_ARG;
hd->current = 0;
hd->found = -1;
/* and reset all resources */
for (i=0; !rc && i < MAX_KEYDB_RESOURCES; i++) {
switch (hd->active[i].type) {
case KEYDB_RESOURCE_TYPE_NONE:
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_search_reset (hd->active[i].u.kr);
break;
}
}
return rc;
}
/*
* Search through all keydb resources, starting at the current position,
* for a keyblock which contains one of the keys described in the DESC array.
*/
int
keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
{
int rc = -1;
if (!hd)
return G10ERR_INV_ARG;
while (rc == -1 && hd->current >= 0 && hd->current < MAX_KEYDB_RESOURCES) {
switch (hd->active[hd->current].type) {
case KEYDB_RESOURCE_TYPE_NONE:
rc = -1; /* no resource = eof */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_search (hd->active[hd->current].u.kr, desc, ndesc);
break;
}
if (rc == -1) /* EOF -> switch to next resource */
hd->current++;
else if (!rc)
hd->found = hd->current;
}
return rc;
}
int
keydb_search_first (KEYDB_HANDLE hd)
{
KEYDB_SEARCH_DESC desc;
memset (&desc, 0, sizeof desc);
desc.mode = KEYDB_SEARCH_MODE_FIRST;
return keydb_search (hd, &desc, 1);
}
int
keydb_search_next (KEYDB_HANDLE hd)
{
KEYDB_SEARCH_DESC desc;
memset (&desc, 0, sizeof desc);
desc.mode = KEYDB_SEARCH_MODE_NEXT;
return keydb_search (hd, &desc, 1);
}
int
keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
{
KEYDB_SEARCH_DESC desc;
memset (&desc, 0, sizeof desc);
desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
desc.u.kid[0] = kid[0];
desc.u.kid[1] = kid[1];
return keydb_search (hd, &desc, 1);
}
int
keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
{
KEYDB_SEARCH_DESC desc;
memset (&desc, 0, sizeof desc);
desc.mode = KEYDB_SEARCH_MODE_FPR;
memcpy (desc.u.fpr, fpr, MAX_FINGERPRINT_LEN);
return keydb_search (hd, &desc, 1);
}

View File

@ -21,15 +21,11 @@
#ifndef G10_KEYDB_H
#define G10_KEYDB_H
#ifdef HAVE_LIBGDBM
#include <gdbm.h>
#endif
#include "types.h"
#include "global.h"
#include "packet.h"
#include "cipher.h"
#define MAX_FINGERPRINT_LEN 20
#define IS_KEY_SIG(s) ((s)->sig_class == 0x1f)
#define IS_UID_SIG(s) (((s)->sig_class & ~3) == 0x10)
@ -50,7 +46,6 @@ typedef struct getkey_ctx_s *GETKEY_CTX;
* This structure is also used to bind arbitrary packets together.
*/
typedef struct kbnode_struct *KBNODE;
struct kbnode_struct {
KBNODE next;
PACKET *pkt;
@ -65,8 +60,7 @@ struct kbnode_struct {
enum resource_type {
rt_UNKNOWN = 0,
rt_RING = 1,
rt_GDBM = 2
rt_RING = 1
};
@ -81,10 +75,6 @@ struct keyblock_pos_struct {
unsigned count; /* length of the keyblock in packets */
IOBUF fp; /* used by enum_keyblocks */
int secret; /* working on a secret keyring */
#ifdef HAVE_LIBGDBM
GDBM_FILE dbf;
byte keybuf[21];
#endif
PACKET *pkt; /* ditto */
int valid;
};
@ -118,6 +108,52 @@ struct pubkey_find_info {
};
typedef struct keydb_handle *KEYDB_HANDLE;
typedef enum {
KEYDB_SEARCH_MODE_NONE,
KEYDB_SEARCH_MODE_EXACT,
KEYDB_SEARCH_MODE_SUBSTR,
KEYDB_SEARCH_MODE_MAIL,
KEYDB_SEARCH_MODE_MAILSUB,
KEYDB_SEARCH_MODE_MAILEND,
KEYDB_SEARCH_MODE_WORDS,
KEYDB_SEARCH_MODE_SHORT_KID,
KEYDB_SEARCH_MODE_LONG_KID,
KEYDB_SEARCH_MODE_TDBIDX,
KEYDB_SEARCH_MODE_FPR16,
KEYDB_SEARCH_MODE_FPR20,
KEYDB_SEARCH_MODE_FPR,
KEYDB_SEARCH_MODE_FIRST,
KEYDB_SEARCH_MODE_NEXT
} KeydbSearchMode;
struct keydb_search_desc {
KeydbSearchMode mode;
union {
const char *name;
char fpr[MAX_FINGERPRINT_LEN];
u32 kid[2];
} u;
};
/*-- keydb.c --*/
int keydb_add_resource (const char *url, int force, int secret);
KEYDB_HANDLE keydb_new (int secret);
void keydb_release (KEYDB_HANDLE hd);
const char *keydb_get_resource_name (KEYDB_HANDLE hd);
int keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb);
int keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb);
int keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb);
int keydb_delete_keyblock (KEYDB_HANDLE hd);
int keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved);
int keydb_search_reset (KEYDB_HANDLE hd);
int keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
int keydb_search_first (KEYDB_HANDLE hd);
int keydb_search_next (KEYDB_HANDLE hd);
int keydb_search_kid (KEYDB_HANDLE hd, u32 *kid);
int keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr);
/*-- pkclist.c --*/
int check_signatures_trust( PKT_signature *sig );
@ -147,8 +183,8 @@ void cache_public_key( PKT_public_key *pk );
void getkey_disable_caches(void);
int get_pubkey( PKT_public_key *pk, u32 *keyid );
KBNODE get_pubkeyblock( u32 *keyid );
int get_pubkey_byname( GETKEY_CTX *rx, PKT_public_key *pk,
const char *name, KBNODE *ret_keyblock );
int get_pubkey_byname( PKT_public_key *pk, const char *name,
KBNODE *ret_keyblock, KEYDB_HANDLE *ret_kdbhd);
int get_pubkey_bynames( GETKEY_CTX *rx, PKT_public_key *pk,
STRLIST names, KBNODE *ret_keyblock );
int get_pubkey_next( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock );
@ -213,25 +249,4 @@ void clear_kbnode_flags( KBNODE n );
int commit_kbnode( KBNODE *root );
void dump_kbnode( KBNODE node );
/*-- ringedit.c --*/
const char *enum_keyblock_resources( int *sequence, int secret );
int add_keyblock_resource( const char *resname, int force, int secret );
const char *keyblock_resource_name( KBPOS *kbpos );
int get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos );
char *get_writable_keyblock_file( int secret );
int find_keyblock( PUBKEY_FIND_INFO info, KBPOS *kbpos );
int find_keyblock_byname( KBPOS *kbpos, const char *username );
int find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk );
int find_secret_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk );
int find_secret_keyblock_byname( KBPOS *kbpos, const char *username );
int find_secret_keyblock_direct (KBPOS *kbpos, u32 *keyid);
int lock_keyblock( KBPOS *kbpos );
void unlock_keyblock( KBPOS *kbpos );
int read_keyblock( KBPOS *kbpos, KBNODE *ret_root );
int enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root );
int insert_keyblock( KBPOS *kbpos, KBNODE root );
int delete_keyblock( KBPOS *kbpos );
int update_keyblock( KBPOS *kbpos, KBNODE root );
#endif /*G10_KEYDB_H*/

View File

@ -84,30 +84,6 @@ struct sign_attrib {
static int
get_keyblock_byname( KBNODE *keyblock, KBPOS *kbpos, const char *username )
{
int rc;
*keyblock = NULL;
/* search the userid */
rc = find_keyblock_byname( kbpos, username );
if( rc ) {
log_error(_("%s: user not found\n"), username );
return rc;
}
/* read the keyblock */
rc = read_keyblock( kbpos, keyblock );
if( rc )
log_error("%s: keyblock read problem: %s\n", username, g10_errstr(rc));
else
merge_keys_and_selfsig( *keyblock );
return rc;
}
/****************
* Print information about a signature, check it and return true
* if the signature is okay. NODE must be a signature packet.
@ -626,9 +602,9 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
enum cmdids cmd = 0;
int rc = 0;
KBNODE keyblock = NULL;
KBPOS keyblockpos;
KEYDB_HANDLE kdbhd = NULL;
KBNODE sec_keyblock = NULL;
KBPOS sec_keyblockpos;
KEYDB_HANDLE sec_kdbhd = NULL;
KBNODE cur_keyblock;
char *answer = NULL;
int redisplay = 1;
@ -651,7 +627,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
}
/* get the public key */
rc = get_keyblock_byname( &keyblock, &keyblockpos, username );
rc = get_pubkey_byname (NULL, username, &keyblock, &kdbhd);
if( rc )
goto leave;
if( fix_keyblock( keyblock ) )
@ -662,18 +638,34 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
if( !sign_mode ) {/* see whether we have a matching secret key */
PKT_public_key *pk = keyblock->pkt->pkt.public_key;
rc = find_secret_keyblock_bypk( &sec_keyblockpos, pk );
if( !rc ) {
rc = read_keyblock( &sec_keyblockpos, &sec_keyblock );
if( rc ) {
log_error("%s: secret keyblock read problem: %s\n",
sec_kdbhd = keydb_new (1);
{
byte afp[MAX_FINGERPRINT_LEN];
size_t an;
fingerprint_from_pk (pk, afp, &an);
while (an < MAX_FINGERPRINT_LEN)
afp[an++] = 0;
rc = keydb_search_fpr (sec_kdbhd, afp);
}
if (!rc) {
rc = keydb_get_keyblock (sec_kdbhd, &sec_keyblock);
if (rc) {
log_error (_("error reading secret keyblock `%s': %s\n"),
username, g10_errstr(rc));
goto leave;
}
merge_keys_and_selfsig( sec_keyblock );
if( fix_keyblock( sec_keyblock ) )
sec_modified++;
else {
merge_keys_and_selfsig( sec_keyblock );
if( fix_keyblock( sec_keyblock ) )
sec_modified++;
}
}
if (rc) {
sec_keyblock = NULL;
keydb_release (sec_kdbhd); sec_kdbhd = NULL;
rc = 0;
}
}
if( sec_keyblock ) {
@ -1012,23 +1004,24 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
do_cmd_save:
if( modified || sec_modified ) {
if( modified ) {
rc = update_keyblock( &keyblockpos, keyblock );
rc = keydb_update_keyblock (kdbhd, keyblock);
if( rc ) {
log_error(_("update failed: %s\n"), g10_errstr(rc) );
break;
}
}
if( sec_modified ) {
rc = update_keyblock( &sec_keyblockpos, sec_keyblock );
rc = keydb_update_keyblock (sec_kdbhd, sec_keyblock );
if( rc ) {
log_error(_("update secret failed: %s\n"),
g10_errstr(rc) );
log_error( _("update secret failed: %s\n"),
g10_errstr(rc) );
break;
}
}
}
else
tty_printf(_("Key not changed so no update needed.\n"));
/* TODO: we should keep track whether we have changed
* something relevant to the trustdb */
if( !modified && sign_mode )
@ -1051,6 +1044,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
leave:
release_kbnode( keyblock );
release_kbnode( sec_keyblock );
keydb_release (kdbhd);
m_free(answer);
}

View File

@ -284,22 +284,22 @@ static void
add_feature_mdc (PKT_signature *sig)
{
const byte *s;
size_t i, n;
size_t n;
char *buf;
s = parse_sig_subpkt (sig->hashed, SIGSUBPKT_FEATURES, &n );
if (!s)
n = 0;
for (i=0; i < n; i++ ) {
if (s[i] == 1)
return; /* already set */
if (s && n && (s[0] & 0x01))
return; /* already set */
if (!s || !n) { /* create a new one */
n = 1;
buf = m_alloc (n);
}
buf = m_alloc (n+1);
buf[0] = 1; /* MDC feature */
memcpy (buf+1, s, n);
build_sig_subpkt (sig, SIGSUBPKT_FEATURES, buf, n+1);
else {
buf = m_alloc (n);
memcpy (buf, s, n);
}
buf[0] |= 0x01; /* MDC feature */
build_sig_subpkt (sig, SIGSUBPKT_FEATURES, buf, n);
m_free (buf);
}
@ -1769,8 +1769,6 @@ static void
do_generate_keypair( struct para_data_s *para,
struct output_control_s *outctrl )
{
char *pub_fname = NULL;
char *sec_fname = NULL;
KBNODE pub_root = NULL;
KBNODE sec_root = NULL;
PKT_secret_key *sk = NULL;
@ -1823,20 +1821,14 @@ do_generate_keypair( struct para_data_s *para,
&outctrl->sec.afx );
}
}
pub_fname = outctrl->pub.fname; /* only for info output */
sec_fname = outctrl->sec.fname; /* only for info output */
assert( outctrl->pub.stream );
assert( outctrl->sec.stream );
}
else {
pub_fname = get_writable_keyblock_file( 0 );
sec_fname = get_writable_keyblock_file( 1 );
if( opt.verbose ) {
log_info(_("writing public key to `%s'\n"), outctrl->pub.fname );
log_info(_("writing secret key to `%s'\n"), outctrl->sec.fname );
}
}
if( opt.verbose ) {
log_info(_("writing public key to `%s'\n"), pub_fname );
log_info(_("writing secret key to `%s'\n"), sec_fname );
}
/* we create the packets as a tree of kbnodes. Because the structure
* we create is known in advance we simply generate a linked list
@ -1895,46 +1887,47 @@ do_generate_keypair( struct para_data_s *para,
}
else if( !rc ) { /* write to the standard keyrings */
KBPOS pub_kbpos;
KBPOS sec_kbpos;
int rc1 = -1;
int rc2 = -1;
KEYDB_HANDLE pub_hd = keydb_new (0);
KEYDB_HANDLE sec_hd = keydb_new (1);
/* we can now write the certificates */
if( get_keyblock_handle( pub_fname, 0, &pub_kbpos ) ) {
if( add_keyblock_resource( pub_fname, 1, 0 ) ) {
log_error("can add keyblock file `%s'\n", pub_fname );
rc = G10ERR_CREATE_FILE;
}
else if( get_keyblock_handle( pub_fname, 0, &pub_kbpos ) ) {
log_error("can get keyblock handle for `%s'\n", pub_fname );
rc = G10ERR_CREATE_FILE;
}
}
if( rc )
;
else if( get_keyblock_handle( sec_fname, 1, &sec_kbpos ) ) {
if( add_keyblock_resource( sec_fname, 1, 1 ) ) {
log_error("can add keyblock file `%s'\n", sec_fname );
rc = G10ERR_CREATE_FILE;
}
else if( get_keyblock_handle( sec_fname, 1, &sec_kbpos ) ) {
log_error("can get keyblock handle for `%s'\n", sec_fname );
rc = G10ERR_CREATE_FILE;
}
}
/* FIXME: we may have to create the keyring first */
rc = keydb_locate_writable (pub_hd, NULL);
if (rc)
log_error (_("no writable public keyring found: %s\n"),
g10_errstr (rc));
if( rc )
;
else if( (rc=rc1=lock_keyblock( &pub_kbpos )) )
log_error("can't lock public keyring: %s\n", g10_errstr(rc) );
else if( (rc=rc2=lock_keyblock( &sec_kbpos )) )
log_error("can't lock secret keyring: %s\n", g10_errstr(rc) );
else if( (rc=insert_keyblock( &pub_kbpos, pub_root )) )
log_error("can't write public key: %s\n", g10_errstr(rc) );
else if( (rc=insert_keyblock( &sec_kbpos, sec_root )) )
log_error("can't write secret key: %s\n", g10_errstr(rc) );
else {
if (!rc) {
rc = keydb_locate_writable (sec_hd, NULL);
if (rc)
log_error (_("no writable secret keyring found: %s\n"),
g10_errstr (rc));
}
if (!rc && opt.verbose) {
log_info(_("writing public key to `%s'\n"),
keydb_get_resource_name (pub_hd));
log_info(_("writing secret key to `%s'\n"),
keydb_get_resource_name (sec_hd));
}
if (!rc) {
rc = keydb_insert_keyblock (pub_hd, pub_root);
if (rc)
log_error (_("error writing public keyring `%s': %s\n"),
keydb_get_resource_name (pub_hd), g10_errstr(rc));
}
if (!rc) {
rc = keydb_insert_keyblock (sec_hd, sec_root);
if (rc)
log_error (_("error writing secret keyring `%s': %s\n"),
keydb_get_resource_name (pub_hd), g10_errstr(rc));
}
keydb_release (pub_hd);
keydb_release (sec_hd);
if (!rc) {
int no_enc_rsa =
get_parameter_algo(para, pKEYTYPE) == PUBKEY_ALGO_RSA
&& get_parameter_uint( para, pKEYUSAGE )
@ -1953,11 +1946,6 @@ do_generate_keypair( struct para_data_s *para,
"secondary key for this purpose.\n") );
}
}
if( !rc1 )
unlock_keyblock( &pub_kbpos );
if( !rc2 )
unlock_keyblock( &sec_kbpos );
}
if( rc ) {
@ -1973,10 +1961,6 @@ do_generate_keypair( struct para_data_s *para,
release_kbnode( sec_root );
if( sk ) /* the unprotected secret key */
free_secret_key(sk);
if( !outctrl->use_files ) {
m_free(pub_fname);
m_free(sec_fname);
}
}

View File

@ -277,7 +277,7 @@ mk_datestr (char *buffer, time_t atime)
struct tm *tp;
if ( atime < 0 ) /* 32 bit time_t and after 2038-01-19 */
strcpy (buffer, "????-??-??"); /* mark this as invalid */
strcpy (buffer, "????" "-??" "-??"); /* mark this as invalid */
else {
tp = gmtime (&atime);
sprintf (buffer,"%04d-%02d-%02d",
@ -401,9 +401,9 @@ byte *
fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len )
{
byte *p, *buf;
const char *dp;
const byte *dp;
size_t len;
unsigned n;
unsigned int n;
if( pk->version < 4 && is_RSA(pk->pubkey_algo) ) {
/* RSA in version 3 packets is special */
@ -434,6 +434,8 @@ fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len )
if( !array )
array = m_alloc( len );
memcpy(array, dp, len );
pk->keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
pk->keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
md_close(md);
}

View File

@ -67,41 +67,50 @@ secret_key_list( STRLIST list )
static void
list_all( int secret )
{
KBPOS kbpos;
KEYDB_HANDLE hd;
KBNODE keyblock = NULL;
int rc=0;
int lastresno;
const char *lastresname, *resname;
rc = enum_keyblocks( secret? 5:0, &kbpos, &keyblock );
hd = keydb_new (secret);
if (!hd)
rc = G10ERR_GENERAL;
else
rc = keydb_search_first (hd);
if( rc ) {
if( rc != -1 )
log_error("enum_keyblocks(open) failed: %s\n", g10_errstr(rc) );
log_error("keydb_search_first failed: %s\n", g10_errstr(rc) );
goto leave;
}
lastresno = -1;
while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) {
if( lastresno != kbpos.resno ) {
const char *s = keyblock_resource_name( &kbpos );
lastresname = NULL;
do {
rc = keydb_get_keyblock (hd, &keyblock);
if (rc) {
log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc));
goto leave;
}
resname = keydb_get_resource_name (hd);
if (lastresname != resname ) {
int i;
lastresno = kbpos.resno;
printf("%s\n", s );
for(i=strlen(s); i; i-- )
printf("%s\n", resname );
for(i=strlen(resname); i; i-- )
putchar('-');
putchar('\n');
lastresname = resname;
}
merge_keys_and_selfsig( keyblock );
list_keyblock( keyblock, secret );
release_kbnode( keyblock ); keyblock = NULL;
}
release_kbnode( keyblock );
keyblock = NULL;
} while (!(rc = keydb_search_next (hd)));
if( rc && rc != -1 )
log_error("enum_keyblocks(read) failed: %s\n", g10_errstr(rc));
log_error ("keydb_search_next failed: %s\n", g10_errstr(rc));
leave:
enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
release_kbnode( keyblock );
release_kbnode (keyblock);
keydb_release (hd);
}

1061
g10/keyring.c Normal file

File diff suppressed because it is too large Load Diff

44
g10/keyring.h Normal file
View File

@ -0,0 +1,44 @@
/* keyring.h - Keyring operations
* Copyright (C) 2001 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
*/
#ifndef GPG_KEYRING_H
#define GPG_KEYRING_H 1
#include "global.h"
typedef struct keyring_handle *KEYRING_HANDLE;
void keyring_register_filename (const char *fname, int secret);
KEYRING_HANDLE keyring_new (int secret);
void keyring_release (KEYRING_HANDLE hd);
const char *keyring_get_resource_name (KEYRING_HANDLE hd);
int keyring_lock (KEYRING_HANDLE hd, int yes);
int keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb);
int keyring_update_keyblock (KEYRING_HANDLE hd, KBNODE kb);
int keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb);
int keyring_delete_keyblock (KEYRING_HANDLE hd);
int keyring_search_reset (KEYRING_HANDLE hd);
int keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
#endif /*GPG_KEYRING_H*/

BIN
g10/keyring.o Normal file

Binary file not shown.

View File

@ -755,7 +755,7 @@ print_notation_data( PKT_signature *sig )
write_status_buffer ( STATUS_POLICY_URL, p, n, 0 );
}
/* Now check wheter the key of this signature has some
/* Now check whether the key of this signature has some
* notation data */
/* TODO */

View File

@ -50,6 +50,7 @@ struct {
int check_sigs; /* check key signatures */
int with_colons;
int with_key_data;
int with_fingerprint; /* opt --with-fingerprint active */
int fingerprint; /* list fingerprints */
int list_sigs; /* list signatures */
int no_armor;

View File

@ -323,7 +323,7 @@ int list_packets( IOBUF a );
int set_packet_list_mode( int mode );
#if DEBUG_PARSE_PACKET
int dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos,
int dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid,
const char* file, int lineno );
int dbg_parse_packet( IOBUF inp, PACKET *ret_pkt,
const char* file, int lineno );
@ -333,8 +333,8 @@ int dbg_copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff,
const char* file, int lineno );
int dbg_skip_some_packets( IOBUF inp, unsigned n,
const char* file, int lineno );
#define search_packet( a,b,c ) \
dbg_search_packet( (a), (b), (c), __FILE__, __LINE__ )
#define search_packet( a,b,c,d ) \
dbg_search_packet( (a), (b), (c), (d), __FILE__, __LINE__ )
#define parse_packet( a, b ) \
dbg_parse_packet( (a), (b), __FILE__, __LINE__ )
#define copy_all_packets( a,b ) \
@ -344,7 +344,7 @@ int dbg_skip_some_packets( IOBUF inp, unsigned n,
#define skip_some_packets( a,b ) \
dbg_skip_some_packets((a),(b), __FILE__, __LINE__ )
#else
int search_packet( IOBUF inp, PACKET *pkt, off_t *retpos );
int search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid );
int parse_packet( IOBUF inp, PACKET *ret_pkt);
int copy_all_packets( IOBUF inp, IOBUF out );
int copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff );

View File

@ -158,24 +158,24 @@ parse_packet( IOBUF inp, PACKET *pkt )
*/
#ifdef DEBUG_PARSE_PACKET
int
dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos,
dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid,
const char *dbg_f, int dbg_l )
{
int skip, rc;
do {
rc = parse( inp, pkt, 1, retpos, &skip, NULL, 0, "search", dbg_f, dbg_l );
rc = parse( inp, pkt, with_uid?2:1, retpos, &skip, NULL, 0, "search", dbg_f, dbg_l );
} while( skip );
return rc;
}
#else
int
search_packet( IOBUF inp, PACKET *pkt, off_t *retpos )
search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid )
{
int skip, rc;
do {
rc = parse( inp, pkt, 1, retpos, &skip, NULL, 0 );
rc = parse( inp, pkt, with_uid?2:1, retpos, &skip, NULL, 0 );
} while( skip );
return rc;
}
@ -296,6 +296,7 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
byte hdr[8];
int hdrlen;
int new_ctb = 0;
int with_uid = (onlykeypkts == 2);
*skip = 0;
assert( !pkt->pkt.generic );
@ -309,7 +310,7 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
hdrlen=0;
hdr[hdrlen++] = ctb;
if( !(ctb & 0x80) ) {
log_error("%s: invalid packet (ctb=%02x)\n", iobuf_where(inp), ctb );
log_error("%s: invalid packet (ctb=%02x)\n", iobuf_where(inp), ctb );
rc = G10ERR_INVALID_PACKET;
goto leave;
}
@ -375,12 +376,14 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
goto leave;
}
if( do_skip
if (with_uid && pkttype == PKT_USER_ID)
;
else if( do_skip
|| !pkttype
|| (onlykeypkts && pkttype != PKT_PUBLIC_SUBKEY
&& pkttype != PKT_PUBLIC_KEY
&& pkttype != PKT_SECRET_SUBKEY
&& pkttype != PKT_SECRET_KEY ) ) {
&& pkttype != PKT_SECRET_KEY ) ) {
skip_rest(inp, pktlen);
*skip = 1;
rc = 0;
@ -866,7 +869,7 @@ dump_sig_subpkt( int hashed, int type, int critical,
case SIGSUBPKT_FEATURES:
fputs ( "features:", stdout );
for( i=0; i < length; i++ )
printf(" %d", buffer[i] );
printf(" %02x", buffer[i] );
break;
case SIGSUBPKT_PRIV_VERIFY_CACHE:
p = "verification cache";

View File

@ -285,7 +285,7 @@ agent_get_passphrase ( u32 *keyid, int mode )
char *atext;
char buf[50];
int fd = -1;
int nread;
size_t nread;
u32 reply;
char *pw = NULL;
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
@ -433,7 +433,7 @@ passphrase_clear_cache ( u32 *keyid, int algo )
size_t n;
char buf[50];
int fd = -1;
int nread;
size_t nread;
u32 reply;
PKT_public_key *pk;
byte fpr[MAX_FINGERPRINT_LEN];

View File

@ -628,7 +628,10 @@ check_signatures_trust( PKT_signature *sig )
if( opt.always_trust ) {
if( !opt.quiet )
log_info(_("WARNING: Using untrusted key!\n"));
return 0;
if (opt.with_fingerprint)
fpr_info (pk);
rc = 0;
goto leave;
}
@ -705,6 +708,8 @@ check_signatures_trust( PKT_signature *sig )
write_status( STATUS_TRUST_NEVER );
log_info(_("WARNING: We do NOT trust this key!\n"));
log_info(_(" The signature is probably a FORGERY.\n"));
if (opt.with_fingerprint)
fpr_info (pk);
rc = G10ERR_BAD_SIGN;
break;
@ -721,10 +726,14 @@ check_signatures_trust( PKT_signature *sig )
case TRUST_FULLY:
write_status( STATUS_TRUST_FULLY );
if (opt.with_fingerprint)
fpr_info (pk);
break;
case TRUST_ULTIMATE:
write_status( STATUS_TRUST_ULTIMATE );
if (opt.with_fingerprint)
fpr_info (pk);
break;
default: BUG();
@ -814,10 +823,12 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
else if( (use & PUBKEY_USAGE_ENC) && !opt.no_encrypt_to ) {
pk = m_alloc_clear( sizeof *pk );
pk->req_usage = use;
if( (rc = get_pubkey_byname( NULL, pk, rov->d, NULL )) ) {
if( (rc = get_pubkey_byname( pk, rov->d, NULL, NULL )) ) {
free_public_key( pk ); pk = NULL;
log_error(_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) );
}
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
rov->d, strlen (rov->d), -1);
}
else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) {
/* Skip the actual key if the key is already present
* in the list */
@ -838,6 +849,8 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
else {
free_public_key( pk ); pk = NULL;
log_error(_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) );
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
rov->d, strlen (rov->d), -1);
}
}
}
@ -870,7 +883,7 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
free_public_key( pk );
pk = m_alloc_clear( sizeof *pk );
pk->req_usage = use;
rc = get_pubkey_byname( NULL, pk, answer, NULL );
rc = get_pubkey_byname( pk, answer, NULL, NULL );
if( rc )
tty_printf(_("No such user ID.\n"));
else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) {
@ -936,7 +949,7 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
else if( !any_recipients && (def_rec = default_recipient()) ) {
pk = m_alloc_clear( sizeof *pk );
pk->req_usage = use;
rc = get_pubkey_byname( NULL, pk, def_rec, NULL );
rc = get_pubkey_byname( pk, def_rec, NULL, NULL );
if( rc )
log_error(_("unknown default recipient `%s'\n"), def_rec );
else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) {
@ -961,9 +974,12 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
pk = m_alloc_clear( sizeof *pk );
pk->req_usage = use;
if( (rc = get_pubkey_byname( NULL, pk, remusr->d, NULL )) ) {
if( (rc = get_pubkey_byname( pk, remusr->d, NULL, NULL )) ) {
free_public_key( pk ); pk = NULL;
log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) );
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
remusr->d, strlen (remusr->d),
-1);
}
else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) {
int trustlevel;
@ -973,11 +989,19 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
free_public_key( pk ); pk = NULL;
log_error(_("%s: error checking key: %s\n"),
remusr->d, g10_errstr(rc) );
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
remusr->d,
strlen (remusr->d),
-1);
}
else if( (trustlevel & TRUST_FLAG_DISABLED) ) {
free_public_key(pk); pk = NULL;
log_info(_("%s: skipped: public key is disabled\n"),
remusr->d);
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
remusr->d,
strlen (remusr->d),
-1);
}
else if( do_we_trust_pre( pk, trustlevel ) ) {
/* note: do_we_trust may have changed the trustlevel */
@ -1004,10 +1028,18 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
}
else { /* we don't trust this pk */
free_public_key( pk ); pk = NULL;
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
remusr->d,
strlen (remusr->d),
-1);
}
}
else {
free_public_key( pk ); pk = NULL;
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
remusr->d,
strlen (remusr->d),
-1);
log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) );
}
}

View File

@ -87,41 +87,46 @@ gen_revoke( const char *uname )
IOBUF out = NULL;
KBNODE keyblock = NULL;
KBNODE node;
KBPOS kbpos;
KEYDB_HANDLE kdbhd;
struct revocation_reason_info *reason = NULL;
KEYDB_SEARCH_DESC desc;
if( opt.batch ) {
log_error(_("sorry, can't do this in batch mode\n"));
return G10ERR_GENERAL;
}
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx);
init_packet( &pkt );
/* search the userid */
rc = find_secret_keyblock_byname( &kbpos, uname );
if( rc ) {
log_error(_("secret key for user `%s' not found\n"), uname );
/* search the userid:
* We don't want the whole getkey stuff here but the entire keyblock
*/
kdbhd = keydb_new (1);
memset (&desc, 0, sizeof desc);
desc.mode = classify_user_id (uname,
desc.u.kid,
desc.u.fpr,
&desc.u.name,
NULL);
rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID;
if (rc) {
log_error (_("secret key `%s' not found: %s\n"),
uname, g10_errstr (rc));
goto leave;
}
/* read the keyblock */
rc = read_keyblock( &kbpos, &keyblock );
rc = keydb_get_keyblock (kdbhd, &keyblock );
if( rc ) {
log_error(_("error reading the certificate: %s\n"), g10_errstr(rc) );
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
goto leave;
}
/* get the keyid from the keyblock */
node = find_kbnode( keyblock, PKT_SECRET_KEY );
if( !node ) { /* maybe better to use log_bug ? */
log_error(_("Oops; secret key not found anymore!\n"));
rc = G10ERR_GENERAL;
goto leave;
}
if( !node )
BUG ();
/* fixme: should make a function out of this stuff,
* it's used all over the source */
@ -139,6 +144,8 @@ gen_revoke( const char *uname )
tty_printf("\n");
}
pk = m_alloc_clear( sizeof *pk );
/* FIXME: We should get the public key direct from the secret one */
rc = get_pubkey( pk, sk_keyid );
if( rc ) {
log_error(_("no corresponding public key: %s\n"), g10_errstr(rc) );
@ -224,6 +231,7 @@ gen_revoke( const char *uname )
if( sig )
free_seckey_enc( sig );
release_kbnode( keyblock );
keydb_release (kdbhd);
if( rc )
iobuf_cancel(out);
else

File diff suppressed because it is too large Load Diff

View File

@ -140,6 +140,7 @@ get_status_string ( int no )
case STATUS_KEY_CREATED : s = "KEY_CREATED"; break;
case STATUS_USERID_HINT : s = "USERID_HINT"; break;
case STATUS_UNEXPECTED : s = "UNEXPECTED"; break;
case STATUS_INV_RECP : s = "INV_RECP"; break;
default: s = "?"; break;
}
return s;

View File

@ -90,6 +90,8 @@
#define STATUS_KEY_CREATED 58
#define STATUS_USERID_HINT 59
#define STATUS_UNEXPECTED 60
#define STATUS_INV_RECP 61
/*-- status.c --*/
void set_status_fd ( int fd );

View File

@ -352,7 +352,7 @@ list_trustdb( const char *username )
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
int rc;
if( (rc = get_pubkey_byname( NULL, pk, username, NULL )) )
if( (rc = get_pubkey_byname( pk, username, NULL, NULL )) )
log_error(_("user '%s' not found: %s\n"), username, g10_errstr(rc) );
else if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 )
log_error(_("problem finding '%s' in trustdb: %s\n"),

View File

@ -1697,22 +1697,28 @@ void
update_trustdb()
{
KBNODE keyblock = NULL;
KBPOS kbpos;
KEYDB_HANDLE kdbhd;
int rc;
if( opt.dry_run )
return;
init_trustdb();
rc = enum_keyblocks( 0, &kbpos, &keyblock );
if( !rc ) {
kdbhd = keydb_new (0);
rc = keydb_search_first (kdbhd);
if (!rc) {
ulong count=0, err_count=0, new_count=0;
while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) {
/*int modified;*/
do {
TRUSTREC drec;
PKT_public_key *pk = find_kbnode( keyblock, PKT_PUBLIC_KEY )
->pkt->pkt.public_key;
PKT_public_key *pk;
/*int modified;*/
rc = keydb_get_keyblock (kdbhd, &keyblock );
if (rc)
break;
pk = find_kbnode (keyblock, PKT_PUBLIC_KEY)->pkt->pkt.public_key;
rc = get_dir_record( pk, &drec );
if( rc == -1 ) { /* not in trustdb: insert */
@ -1741,7 +1747,7 @@ update_trustdb()
release_kbnode( keyblock ); keyblock = NULL;
if( !(++count % 100) )
log_info(_("%lu keys so far processed\n"), count);
}
} while ( !(rc = keydb_search_next (kdbhd)));
log_info(_("%lu keys processed\n"), count);
if( err_count )
log_info(_("\t%lu keys with errors\n"), err_count);
@ -1751,7 +1757,7 @@ update_trustdb()
if( rc && rc != -1 )
log_error(_("enumerate keyblocks failed: %s\n"), g10_errstr(rc));
enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
keydb_release (kdbhd);
release_kbnode( keyblock );
}
@ -2514,7 +2520,7 @@ list_trust_path( const char *username )
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
init_trustdb();
if( (rc = get_pubkey_byname(NULL, pk, username, NULL )) )
if( (rc = get_pubkey_byname (pk, username, NULL, NULL )) )
log_error(_("user '%s' not found: %s\n"), username, g10_errstr(rc) );
else if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 )
log_error(_("problem finding '%s' in trustdb: %s\n"),

View File

@ -120,7 +120,7 @@ if (gettext --version </dev/null 2>/dev/null | awk 'NR==1 { split($4,A,"\."); \
X=10000*A[1]+100*A[2]+A[3]; echo X; if( X >= 1038 ) exit 1; exit 0}')
then
echo "**Error**: You must have "\`gettext\'" installed to compile $PGM."
echo ' (version 0.10.35 or newer is required; get'
echo ' (version 0.10.38 or newer is required; get'
echo ' ftp://alpha.gnu.org/gnu/gettext/gettext-0.10.38.tar.gz'
echo ' or install the latest Debian package)'
DIE="yes"

View File

@ -49,7 +49,6 @@ enum cmd_and_opt_values { aNull = 0,
oPrefix = 'p',
aTest };
#warning Add an option to split a keyring into reasonable sized chunks.
static ARGPARSE_OPTS opts[] = {

View File

@ -1,3 +1,7 @@
2001-09-03 Werner Koch <wk@gnupg.org>
* miscutil.c (strtimestamp,asctimestamp): Avoid trigraphs.
2001-08-21 Stefan Bellon <sbellon@sbellon.de>
* riscos.c [__riscos__] (close_fds): Fixed possible endless loop.

View File

@ -126,7 +126,7 @@ strtimestamp( u32 stamp )
time_t atime = stamp;
if (atime < 0) {
strcpy (buffer, "????-??-??");
strcpy (buffer, "????" "-??" "-??");
}
else {
tp = gmtime( &atime );
@ -150,7 +150,7 @@ asctimestamp( u32 stamp )
time_t atime = stamp;
if (atime < 0) {
strcpy (buffer, "????-??-??");
strcpy (buffer, "????" "-??" "-??");
return buffer;
}