1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-05-31 22:18:03 +02:00

See ChangeLog: Wed Mar 17 13:09:03 CET 1999 Werner Koch

This commit is contained in:
Werner Koch 1999-03-17 12:13:04 +00:00
parent dafcce0177
commit 8d255ff264
27 changed files with 863 additions and 286 deletions

2
NEWS
View File

@ -4,6 +4,8 @@
* A bunch of changes to the key validation code. * A bunch of changes to the key validation code.
* --list-trust-path now has an optional --with-colons format.
Noteworthy changes in version 0.9.4 Noteworthy changes in version 0.9.4
----------------------------------- -----------------------------------

25
TODO
View File

@ -1,17 +1,14 @@
* Replace --trusted-keys by a local certificate (which does not get
exported).
* add some status output put for signing and encryption. * add some status output put for signing and encryption.
replace the puc in primegen with some kind of status-fd outputs. replace the putc in primegen with some kind of status-fd outputs.
* Finish the EGD module. * Finish the EGD module.
* Implement 256 bit key Twofish (wait until the 2nd AES conference). * Implement 256 bit key Twofish.
* Check revocation and expire stuff. [I'm currently working on this.] * Check revocation and expire stuff.
* Check calculation of key validity. [I'm currently working on this.] * Check calculation of key validity.
* See why we always get this "Hmmm public key lost" * See why we always get this "Hmmm public key lost"
@ -25,17 +22,11 @@
* when decryptiong multiple key: print a warning only if no usable pubkey * when decryptiong multiple key: print a warning only if no usable pubkey
encrypt package was found. Extension: display a list of all recipients. encrypt package was found. Extension: display a list of all recipients.
* an ERRSIG argument like * Add NO_PUBKEY and NO_SECKEY status lines.
ERRSIG <keyid>, where <keyid> is the id of the missing public key * Add more NODATA status lines
or a new keyword
PUBLIC_MISSING <keyid>
* a status line complaining about a missing secret key like
SECRET_MISSING <keyid>, where <keyid> is the id of the missing secret key
* a status line complaining about a bad passphrase like
BADPASS
* gpg --keyserver wwwkeys.us.pgp.net --importserver 0x12345678
(or --importserver warner@lothar.com, etc)
Nice to have Nice to have

View File

@ -343,4 +343,256 @@ define(GNUPG_CHECK_MLOCK,
]) ])
################################################################
# GNUPG_PROG_NM - find the path to a BSD-compatible name lister
AC_DEFUN(GNUPG_PROG_NM,
[AC_MSG_CHECKING([for BSD-compatible nm])
AC_CACHE_VAL(ac_cv_path_NM,
[if test -n "$NM"; then
# Let the user override the test.
ac_cv_path_NM="$NM"
else
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
for ac_dir in /usr/ucb /usr/ccs/bin $PATH /bin; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/nm; then
# Check to see if the nm accepts a BSD-compat flag.
# Adding the `sed 1q' prevents false positives on HP-UX, which says:
# nm: unknown option "B" ignored
if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
ac_cv_path_NM="$ac_dir/nm -B"
elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
ac_cv_path_NM="$ac_dir/nm -p"
else
ac_cv_path_NM="$ac_dir/nm"
fi
break
fi
done
IFS="$ac_save_ifs"
test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
fi])
NM="$ac_cv_path_NM"
AC_MSG_RESULT([$NM])
AC_SUBST(NM)
])
# GNUPG_SYS_NM_PARSE - Check for command ro grab the raw symbol name followed
# by C symbol name from nm.
AC_DEFUN(GNUPG_SYS_NM_PARSE,
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([GNUPG_PROG_NM])dnl
# Check for command to grab the raw symbol name followed by C symbol from nm.
AC_MSG_CHECKING([command to parse $NM output])
AC_CACHE_VAL(ac_cv_sys_global_symbol_pipe,
[# These are sane defaults that work on at least a few old systems.
# {They come from Ultrix. What could be older than Ultrix?!! ;)}
changequote(,)dnl
# Character class describing NM global symbol codes.
ac_symcode='[BCDEGRSTU]'
# Regexp to match symbols that can be accessed directly from C.
ac_sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
# Transform the above into a raw symbol and a C symbol.
ac_symxfrm='\1 \1'
# Define system-specific variables.
case "$host_os" in
aix*)
ac_symcode='[BCDTU]'
;;
sunos* | cygwin32* | mingw32*)
ac_sympat='_\([_A-Za-z][_A-Za-z0-9]*\)'
ac_symxfrm='_\1 \1'
;;
irix*)
# Cannot use undefined symbols on IRIX because inlined functions mess us up.
ac_symcode='[BCDEGRST]'
;;
solaris*)
ac_symcode='[BDTU]'
;;
esac
# If we're using GNU nm, then use its standard symbol codes.
if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
ac_symcode='[ABCDGISTUW]'
fi
case "$host_os" in
cygwin32* | mingw32*)
# We do not want undefined symbols on cygwin32. The user must
# arrange to define them via -l arguments.
ac_symcode='[ABCDGISTW]'
;;
esac
changequote([,])dnl
# Write the raw and C identifiers.
ac_cv_sys_global_symbol_pipe="sed -n -e 's/^.* $ac_symcode $ac_sympat$/$ac_symxfrm/p'"
# Check to see that the pipe works correctly.
ac_pipe_works=no
cat > conftest.$ac_ext <<EOF
#ifdef __cplusplus
extern "C" {
#endif
char nm_test_var;
void nm_test_func(){}
#ifdef __cplusplus
}
#endif
int main(){nm_test_var='a';nm_test_func;return 0;}
EOF
if AC_TRY_EVAL(ac_compile); then
# Now try to grab the symbols.
ac_nlist=conftest.nm
if AC_TRY_EVAL(NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) && test -s "$ac_nlist"; then
# Try sorting and uniquifying the output.
if sort "$ac_nlist" | uniq > "$ac_nlist"T; then
mv -f "$ac_nlist"T "$ac_nlist"
ac_wcout=`wc "$ac_nlist" 2>/dev/null`
changequote(,)dnl
ac_count=`echo "X$ac_wcout" | sed -e 's,^X,,' -e 's/^[ ]*\([0-9][0-9]*\).*$/\1/'`
changequote([,])dnl
(test "$ac_count" -ge 0) 2>/dev/null || ac_count=-1
else
rm -f "$ac_nlist"T
ac_count=-1
fi
# Make sure that we snagged all the symbols we need.
if egrep ' nm_test_var$' "$ac_nlist" >/dev/null; then
if egrep ' nm_test_func$' "$ac_nlist" >/dev/null; then
cat <<EOF > conftest.c
#ifdef __cplusplus
extern "C" {
#endif
EOF
# Now generate the symbol file.
sed 's/^.* \(.*\)$/extern char \1;/' < "$ac_nlist" >> conftest.c
cat <<EOF >> conftest.c
#if defined (__STDC__) && __STDC__
# define __ptr_t void *
#else
# define __ptr_t char *
#endif
/* The number of symbols in dld_preloaded_symbols, -1 if unsorted. */
int dld_preloaded_symbol_count = $ac_count;
/* The mapping between symbol names and symbols. */
struct {
char *name;
__ptr_t address;
}
changequote(,)dnl
dld_preloaded_symbols[] =
changequote([,])dnl
{
EOF
sed 's/^\(.*\) \(.*\)$/ {"\1", (__ptr_t) \&\2},/' < "$ac_nlist" >> conftest.c
cat <<\EOF >> conftest.c
{0, (__ptr_t) 0}
};
#ifdef __cplusplus
}
#endif
EOF
# Now try linking the two files.
mv conftest.$ac_objext conftestm.$ac_objext
ac_save_LIBS="$LIBS"
ac_save_CFLAGS="$CFLAGS"
LIBS="conftestm.$ac_objext"
CFLAGS="$CFLAGS$no_builtin_flag"
if AC_TRY_EVAL(ac_link) && test -s conftest; then
ac_pipe_works=yes
else
echo "configure: failed program was:" >&AC_FD_CC
cat conftest.c >&AC_FD_CC
fi
LIBS="$ac_save_LIBS"
CFLAGS="$ac_save_CFLAGS"
else
echo "cannot find nm_test_func in $ac_nlist" >&AC_FD_CC
fi
else
echo "cannot find nm_test_var in $ac_nlist" >&AC_FD_CC
fi
else
echo "cannot run $ac_cv_sys_global_symbol_pipe" >&AC_FD_CC
fi
else
echo "$progname: failed program was:" >&AC_FD_CC
cat conftest.c >&AC_FD_CC
fi
rm -rf conftest*
# Do not use the global_symbol_pipe unless it works.
test "$ac_pipe_works" = yes || ac_cv_sys_global_symbol_pipe=
])
ac_result=yes
if test -z "$ac_cv_sys_global_symbol_pipe"; then
ac_result=no
fi
AC_MSG_RESULT($ac_result)
])
# GNUPG_SYS_LIBTOOL_CYGWIN32 - find tools needed on cygwin32
AC_DEFUN(GNUPG_SYS_LIBTOOL_CYGWIN32,
[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
AC_CHECK_TOOL(AS, as, false)
])
# GNUPG_SYS_SYMBOL_UNDERSCORE - does the compiler prefix global symbols
# with an underscore?
AC_DEFUN(GNUPG_SYS_SYMBOL_UNDERSCORE,
[AC_REQUIRE([GNUPG_PROG_NM])dnl
AC_REQUIRE([GNUPG_SYS_NM_PARSE])dnl
AC_MSG_CHECKING([for _ prefix in compiled symbols])
AC_CACHE_VAL(ac_cv_sys_symbol_underscore,
[ac_cv_sys_symbol_underscore=no
cat > conftest.$ac_ext <<EOF
void nm_test_func(){}
int main(){nm_test_func;return 0;}
EOF
if AC_TRY_EVAL(ac_compile); then
# Now try to grab the symbols.
ac_nlist=conftest.nm
if AC_TRY_EVAL(NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) && test -s "$ac_nlist"; then
# See whether the symbols have a leading underscore.
if egrep '^_nm_test_func' "$ac_nlist" >/dev/null; then
ac_cv_sys_symbol_underscore=yes
else
if egrep '^nm_test_func ' "$ac_nlist" >/dev/null; then
:
else
echo "configure: cannot find nm_test_func in $ac_nlist" >&AC_FD_CC
fi
fi
else
echo "configure: cannot run $ac_cv_sys_global_symbol_pipe" >&AC_FD_CC
fi
else
echo "configure: failed program was:" >&AC_FD_CC
cat conftest.c >&AC_FD_CC
fi
rm -rf conftest*
])
AC_MSG_RESULT($ac_cv_sys_symbol_underscore)
if test x$ac_cv_sys_symbol_underscore = xyes; then
AC_DEFINE(WITH_SYMBOL_UNDERSCORE,1,
[define if compiled symbols have a leading underscore])
fi
])
dnl *-*wedit:notab*-* Please keep this as the last line. dnl *-*wedit:notab*-* Please keep this as the last line.

View File

@ -1,3 +1,7 @@
Wed Mar 17 13:09:03 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* mds.test: replaced the "echo -n"
Mon Mar 8 20:47:17 CET 1999 Werner Koch <wk@isil.d.shuttle.de> Mon Mar 8 20:47:17 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* pubdemo.asc, secdemo.asc: New. * pubdemo.asc, secdemo.asc: New.

View File

@ -89,10 +89,11 @@ Enter passphrase: " { sleep 1; send -- "abc\r" }
expect { expect {
-ex "\r \rRepeat passphrase: " { sleep 1; send -- "abc\r" } -ex "\r \rRepeat passphrase: " { sleep 1; send -- "abc\r" }
timeout { exit 1 } } timeout { exit 1 } }
set timeout 600
expect { expect {
-ex "\r \rWe need to generate a lot of random bytes. It is a good idea to perform\r -ex "\r \rWe need to generate a lot of random bytes. It is a good idea to perform\r
some other action (work in another window, move the mouse, utilize the\r some other action (work in another window, move the mouse, utilize the\r
network and the disks) during the prime generation; this gives the random\r the disks) during the prime generation; this gives the random\r
number generator a better chance to gain enough entropy.\r" {} number generator a better chance to gain enough entropy.\r" {}
timeout { exit 1 } } timeout { exit 1 } }
set timeout 600 set timeout 600

View File

@ -13,7 +13,7 @@ test_one () {
failed="" failed=""
#info Checking message digests #info Checking message digests
echo -n "" | $srcdir/run-gpgm -v --print-mds >y cat /dev/null | $srcdir/run-gpgm -v --print-mds >y
test_one "MD5" "D41D8CD98F00B204E9800998ECF8427E" test_one "MD5" "D41D8CD98F00B204E9800998ECF8427E"
test_one "SHA1" "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709" test_one "SHA1" "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"
test_one "RMD160" "9C1185A5C5E9FC54612808977EE8F548B2258D31" test_one "RMD160" "9C1185A5C5E9FC54612808977EE8F548B2258D31"
@ -25,7 +25,7 @@ fi
[ "$failed" != "" ] && error "$failed failed for empty string" [ "$failed" != "" ] && error "$failed failed for empty string"
echo -n "abcdefghijklmnopqrstuvwxyz" | $srcdir/run-gpgm --print-mds >y /bin/echo "abcdefghijklmnopqrstuvwxyz\c" | $srcdir/run-gpgm --print-mds >y
test_one "MD5" "C3FCD3D76192E4007DFB496CCA67E13B" test_one "MD5" "C3FCD3D76192E4007DFB496CCA67E13B"
test_one "SHA1" "32D10C7B8CF96570CA04CE37F2A19D84240D3A89" test_one "SHA1" "32D10C7B8CF96570CA04CE37F2A19D84240D3A89"
test_one "RMD160" "F71C27109C692C1B56BBDCEB5B9D2865B3708DBC" test_one "RMD160" "F71C27109C692C1B56BBDCEB5B9D2865B3708DBC"

View File

@ -1,3 +1,8 @@
Wed Mar 17 13:09:03 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* rndegd.c (do_read): New.
(gather_random): Changed the implementation.
Mon Mar 8 20:47:17 CET 1999 Werner Koch <wk@isil.d.shuttle.de> Mon Mar 8 20:47:17 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* dynload.c (DLSYM_NEEDS_UNDERSCORE): Renamed. * dynload.c (DLSYM_NEEDS_UNDERSCORE): Renamed.

View File

@ -34,6 +34,7 @@
#include "util.h" #include "util.h"
#include "ttyio.h" #include "ttyio.h"
#include "dynload.h" #include "dynload.h"
#include "cipher.h"
#ifdef IS_MODULE #ifdef IS_MODULE
#define _(a) (a) #define _(a) (a)
@ -64,18 +65,47 @@ do_write( int fd, void *buf, size_t nbytes )
return 0; return 0;
} }
static int
do_read( int fd, void *buf, size_t nbytes )
{
int n, nread = 0;
do {
do {
n = read(fd, (char*)buf + nread, nbytes );
} while( n == -1 && errno == EINTR );
if( n == -1 )
return -1;
nread += n;
} while( nread < nbytes );
return nbytes;
}
/* fixme: level 1 is not yet handled */
static int static int
gather_random( void (*add)(const void*, size_t, int), int requester, gather_random( void (*add)(const void*, size_t, int), int requester,
size_t length, int level ) size_t length, int level )
{ {
static int fd = -1; static int fd = -1;
int n; int n;
int warn=0;
byte buffer[256+2]; byte buffer[256+2];
int nbytes;
int do_restart = 0;
if( !length )
return 0;
restart:
if( do_restart ) {
if( fd != -1 ) {
close( fd );
fd = -1;
}
}
if( fd == -1 ) { if( fd == -1 ) {
const char *name = "/tmp/entropy"; char *name = make_filename( g10_opt_homedir, "entropy", NULL );
struct sockaddr_un addr; struct sockaddr_un addr;
int addr_len; int addr_len;
@ -92,74 +122,64 @@ gather_random( void (*add)(const void*, size_t, int), int requester,
if( connect( fd, (struct sockaddr*)&addr, addr_len) == -1 ) if( connect( fd, (struct sockaddr*)&addr, addr_len) == -1 )
g10_log_fatal("can't connect to `%s': %s\n", g10_log_fatal("can't connect to `%s': %s\n",
name, strerror(errno) ); name, strerror(errno) );
m_free(name);
} }
do_restart = 0;
while( length ) {
fd_set rfds;
struct timeval tv;
int rc;
int nbytes;
int cmd;
nbytes = length < 255? length : 255; nbytes = length < 255? length : 255;
/* send request */ /* first time we do it with a non blocking request */
cmd = level >= 2 ? 2 : 1; buffer[0] = 1; /* non blocking */
buffer[0] = cmd;
buffer[1] = nbytes; buffer[1] = nbytes;
if( do_write( fd, buffer, 2 ) == -1 ) if( do_write( fd, buffer, 2 ) == -1 )
g10_log_fatal("can't write to the EGD: %s\n", strerror(errno) ); g10_log_fatal("can't write to the EGD: %s\n", strerror(errno) );
/* wait on reply */ n = do_read( fd, buffer, 1 );
FD_ZERO(&rfds); if( n == -1 ) {
FD_SET(fd, &rfds); g10_log_error("read error on EGD: %s\n", strerror(errno));
tv.tv_sec = 3; do_restart = 1;
tv.tv_usec = 0; goto restart;
if( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) ) { }
if( !warn ) if( !n ) {
g10_log_error("bad EGD reply: too short\n");
do_restart = 1;
goto restart;
}
if( n > 1 ) {
n--;
(*add)( buffer+1, n, requester );
length -= n;
}
if( length ) {
#ifdef IS_MODULE #ifdef IS_MODULE
fprintf( stderr, fprintf( stderr,
#else #else
tty_printf( tty_printf(
#endif #endif
_( _("Please wait, entropy is being gathered. Do some work if it would\n"
"\n" "keep you from getting bored, because it will improve the quality\n"
"Not enough random bytes available. Please do some other work to give\n" "of the entropy.\n") );
"the OS a chance to collect more entropy! (Need %d more bytes)\n"), length );
warn = 1;
continue;
}
else if( rc == -1 ) {
g10_log_error("select error on EGD: %s\n", strerror(errno));
continue;
} }
while( length ) {
nbytes = length < 255? length : 255;
/* collect reply */ buffer[0] = 2; /* blocking */
do { buffer[1] = nbytes;
n = read(fd, buffer, nbytes+2 ); if( do_write( fd, buffer, 2 ) == -1 )
} while( n == -1 && errno == EINTR ); g10_log_fatal("can't write to the EGD: %s\n", strerror(errno) );
/* process reply */ n = do_read( fd, buffer, nbytes );
if( n == -1 ) if( n == -1 ) {
g10_log_error("read error on EGD: %s\n", strerror(errno)); g10_log_error("read error on EGD: %s\n", strerror(errno));
else if( cmd == 2 && n != nbytes ) { do_restart = 1;
g10_log_error("bad EGD reply: too short %d/%d\n", nbytes, n ); goto restart;
}
if( n != nbytes ) {
g10_log_error("bad EGD reply: too short %d/%d\n", nbytes, n );
do_restart = 1;
goto restart;
} }
else if( cmd == 2 ) {
(*add)( buffer, n, requester ); (*add)( buffer, n, requester );
length -= n; length -= n;
} }
else if( !n )
g10_log_error("bad EGD reply: too short\n");
else if( buffer[0] != n-1 )
g10_log_error("bad EGD reply: count mismatch %d/%d\n",
n-1, buffer[0] );
else if( n==1 )
g10_log_info("no data from EGD\n");
else {
n -= 1;
(*add)( buffer+1, n, requester );
length -= n;
}
}
memset(buffer, 0, sizeof(buffer) ); memset(buffer, 0, sizeof(buffer) );
return 0; /* success */ return 0; /* success */

View File

@ -28,11 +28,11 @@ dnl
dnl Check for random module options dnl Check for random module options
dnl dnl
dnl Fixme: get the list of available modules from MODULES_IN_CIPHER dnl Fixme: get the list of available modules from MODULES_IN_CIPHER
dnl and check agiants this list dnl and check against this list
AC_MSG_CHECKING([which static random module to use]) AC_MSG_CHECKING([which static random module to use])
AC_ARG_ENABLE(static-rnd, AC_ARG_ENABLE(static-rnd,
[ --enable-static-rnd=[egd|unix|linux|nonde] ], [ --enable-static-rnd=[egd|unix|linux|none] ],
[use_static_rnd=$enableval], [use_static_rnd=default] ) [use_static_rnd=$enableval], [use_static_rnd=default] )
if test "$use_static_rnd" = no; then if test "$use_static_rnd" = no; then
@ -169,7 +169,7 @@ case "${target}" in
esac esac
AC_SUBST(MPI_OPT_FLAGS) AC_SUBST(MPI_OPT_FLAGS)
AM_SYS_SYMBOL_UNDERSCORE GNUPG_SYS_SYMBOL_UNDERSCORE
GNUPG_CHECK_PIC GNUPG_CHECK_PIC
GNUPG_CHECK_RDYNAMIC GNUPG_CHECK_RDYNAMIC
if test "$NO_PIC" = yes; then if test "$NO_PIC" = yes; then

View File

@ -54,10 +54,9 @@ more arguments in future versions.
BADSIG <long keyid> <username> BADSIG <long keyid> <username>
The signature with the keyid has not been verified okay. The signature with the keyid has not been verified okay.
ERRSIG ERRSIG <long keyid> <algorithm_number>
It was not possible to check the signature. This may be It was not possible to check the signature. This may be
caused by a missing public key or an unsupported algorithm. caused by a missing public key or an unsupported algorithm.
No argument yet.
VALIDSIG <fingerprint in hex> VALIDSIG <fingerprint in hex>
The signature with the keyid is good. This is the same The signature with the keyid is good. This is the same
@ -72,6 +71,13 @@ more arguments in future versions.
unique ids - others may yield duplicated ones when they unique ids - others may yield duplicated ones when they
have been created in the same second. have been created in the same second.
ENC_TO <long keyid>
The message is encrypted to this keyid.
NODATA <what>
No data has been found. Codes for what are:
1 - No armored data.
TRUST_UNDEFINED TRUST_UNDEFINED
TRUST_NEVER TRUST_NEVER
TRUST_MARGINAL TRUST_MARGINAL
@ -98,10 +104,16 @@ more arguments in future versions.
SHM_GET SHM_GET
SHM_GET_BOOL SHM_GET_BOOL
SHM_GET_HIDDEN SHM_GET_HIDDEN
NEED_PASSPHRASE
[Needs documentation]
NEED_PASSPHRASE <long keyid>
Issued whenever a passphrase is needed.
BAD_PASSPHRASE <long keyid>
The supplied passphrase was wrong
NO_PUBKEY <long keyid>
NO_SECKEY <long keyid>
The key is not available
Key generation Key generation
@ -282,31 +294,6 @@ Record type 8: (shadow directory record)
Record type 9: (cache record) NOT USED
--------------
Used to bind the trustDB to the concrete instance of keyblock in
a pubring. This is used to cache information.
1 byte value 9
1 byte reserved
1 u32 Local-Id.
8 bytes keyid of the primary key (needed?)
1 byte cache-is-valid the following stuff is only
valid if this is set.
1 byte reserved
20 bytes rmd160 hash value over the complete keyblock
This is used to detect any changes of the keyblock with all
CTBs and lengths headers. Calculation is easy if the keyblock
is obtained from a keyserver: simply create the hash from all
received data bytes.
1 byte number of untrusted signatures.
1 byte number of marginal trusted signatures.
1 byte number of fully trusted signatures.
(255 is stored for all values greater than 254)
1 byte Trustlevel (see trustdb.h)
Record Type 10 (hash table) Record Type 10 (hash table)
-------------- --------------
Due to the fact that we use fingerprints to lookup keys, we can Due to the fact that we use fingerprints to lookup keys, we can

View File

@ -1,3 +1,31 @@
Wed Mar 17 13:09:03 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* trustdb.c (check_trust): add new arg add_fnc and changed all callers.
(do_check): Ditto.
(verify_key): Ditto.
(propagate_validity): Use the new add_fnc arg.
(print_user_id): Add the FILE arg.
(propagate_ownertrust): New.
* pkclist.c (add_ownertrust_cb): New and changed the add_ownertrust
logic.
* getkey.c (get_keyblock_bylid): New.
* trustdb.c (print_uid_from_keyblock): New.
(dump_tn_tree_with_colons): New.
(list_trust_path): Add colon print mode.
* trustdb.c (insert_trust_record): Always use the primary key.
* encode.c (encode_simple): Added text_mode filter (Rémi Guyomarch)
(encode_crypt): Ditto.
* mainproc.c (proc_pubkey_enc): Added status ENC_TO.
* armor.c (armor_filter): Added status NODATA.
* passphrase.c (passphrase_to_dek): Always print NEED_PASSPHRASE
* seckey_cert.c (check_secret_key): Added BAD_PASS status.
* g10.c (main): Set g10_opt_homedir.
Sun Mar 14 19:34:36 CET 1999 Werner Koch <wk@isil.d.shuttle.de> Sun Mar 14 19:34:36 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* keygen.c (do_create): Changed wording of the note (Hugh Daniel) * keygen.c (do_create): Changed wording of the note (Hugh Daniel)

View File

@ -989,8 +989,10 @@ armor_filter( void *opaque, int control,
iobuf_writestr(a, tail_strings[afx->what] ); iobuf_writestr(a, tail_strings[afx->what] );
iobuf_writestr(a, "-----\n"); iobuf_writestr(a, "-----\n");
} }
else if( !afx->any_data && !afx->inp_bypass ) else if( !afx->any_data && !afx->inp_bypass ) {
log_error(_("no valid OpenPGP data found.\n")); log_error(_("no valid OpenPGP data found.\n"));
write_status_text( STATUS_NODATA, "1" );
}
if( afx->truncated ) if( afx->truncated )
log_info(_("invalid armor: line longer than %d characters\n"), log_info(_("invalid armor: line longer than %d characters\n"),
MAX_LINELEN ); MAX_LINELEN );

View File

@ -76,11 +76,13 @@ encode_simple( const char *filename, int mode )
cipher_filter_context_t cfx; cipher_filter_context_t cfx;
armor_filter_context_t afx; armor_filter_context_t afx;
compress_filter_context_t zfx; compress_filter_context_t zfx;
text_filter_context_t tfx;
int do_compress = opt.compress && !opt.rfc1991; int do_compress = opt.compress && !opt.rfc1991;
memset( &cfx, 0, sizeof cfx); memset( &cfx, 0, sizeof cfx);
memset( &afx, 0, sizeof afx); memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx); memset( &zfx, 0, sizeof zfx);
memset( &tfx, 0, sizeof tfx);
init_packet(&pkt); init_packet(&pkt);
/* prepare iobufs */ /* prepare iobufs */
@ -90,6 +92,9 @@ encode_simple( const char *filename, int mode )
return G10ERR_OPEN_FILE; return G10ERR_OPEN_FILE;
} }
if( opt.textmode )
iobuf_push_filter( inp, text_filter, &tfx );
cfx.dek = NULL; cfx.dek = NULL;
if( mode ) { if( mode ) {
s2k = m_alloc_clear( sizeof *s2k ); s2k = m_alloc_clear( sizeof *s2k );
@ -151,19 +156,19 @@ encode_simple( const char *filename, int mode )
pt->namelen = 0; pt->namelen = 0;
} }
/* pgp5 has problems to decrypt symmetrically encrypted data from /* pgp5 has problems to decrypt symmetrically encrypted data from
* GnuPOG if the filelength is in the inner packet. It works * GnuPG if the filelength is in the inner packet. It works
* when only partial length headers are use. Until we have * when only partial length headers are use. Until we have
* tracked this problem down. We use this temporary fix * tracked this problem down. We use this temporary fix
* (fixme: remove the && !mode ) * (fixme: remove the && !mode )
*/ */
if( filename && !mode ) { if( filename && !opt.textmode && !mode ) {
if( !(filesize = iobuf_get_filelength(inp)) ) if( !(filesize = iobuf_get_filelength(inp)) )
log_info(_("%s: WARNING: empty file\n"), filename ); log_info(_("%s: WARNING: empty file\n"), filename );
} }
else else
filesize = 0; /* stdin */ filesize = 0; /* stdin */
pt->timestamp = make_timestamp(); pt->timestamp = make_timestamp();
pt->mode = 'b'; pt->mode = opt.textmode? 't' : 'b';
pt->len = filesize; pt->len = filesize;
pt->buf = inp; pt->buf = inp;
pkt.pkttype = PKT_PLAINTEXT; pkt.pkttype = PKT_PLAINTEXT;
@ -206,12 +211,14 @@ encode_crypt( const char *filename, STRLIST remusr )
cipher_filter_context_t cfx; cipher_filter_context_t cfx;
armor_filter_context_t afx; armor_filter_context_t afx;
compress_filter_context_t zfx; compress_filter_context_t zfx;
text_filter_context_t tfx;
PK_LIST pk_list; PK_LIST pk_list;
int do_compress = opt.compress && !opt.rfc1991; int do_compress = opt.compress && !opt.rfc1991;
memset( &cfx, 0, sizeof cfx); memset( &cfx, 0, sizeof cfx);
memset( &afx, 0, sizeof afx); memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx); memset( &zfx, 0, sizeof zfx);
memset( &tfx, 0, sizeof tfx);
init_packet(&pkt); init_packet(&pkt);
if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) ) if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) )
@ -227,6 +234,9 @@ encode_crypt( const char *filename, STRLIST remusr )
else if( opt.verbose ) else if( opt.verbose )
log_info(_("reading from `%s'\n"), filename? filename: "[stdin]"); log_info(_("reading from `%s'\n"), filename? filename: "[stdin]");
if( opt.textmode )
iobuf_push_filter( inp, text_filter, &tfx );
if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) ) if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) )
goto leave; goto leave;
@ -270,14 +280,14 @@ encode_crypt( const char *filename, STRLIST remusr )
pt = m_alloc( sizeof *pt - 1 ); pt = m_alloc( sizeof *pt - 1 );
pt->namelen = 0; pt->namelen = 0;
} }
if( filename ) { if( filename && !opt.textmode ) {
if( !(filesize = iobuf_get_filelength(inp)) ) if( !(filesize = iobuf_get_filelength(inp)) )
log_info(_("%s: WARNING: empty file\n"), filename ); log_info(_("%s: WARNING: empty file\n"), filename );
} }
else else
filesize = 0; /* stdin */ filesize = 0; /* stdin */
pt->timestamp = make_timestamp(); pt->timestamp = make_timestamp();
pt->mode = 'b'; pt->mode = opt.textmode ? 't' : 'b';
pt->len = filesize; pt->len = filesize;
pt->new_ctb = !pt->len && !opt.rfc1991; pt->new_ctb = !pt->len && !opt.rfc1991;
pt->buf = inp; pt->buf = inp;

View File

@ -824,6 +824,7 @@ main( int argc, char **argv )
secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */ secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */
set_debug(); set_debug();
g10_opt_homedir = opt.homedir;
/* must do this after dropping setuid, because string_to... /* must do this after dropping setuid, because string_to...
* may try to load an module */ * may try to load an module */

View File

@ -31,6 +31,7 @@
#include "keydb.h" #include "keydb.h"
#include "options.h" #include "options.h"
#include "main.h" #include "main.h"
#include "trustdb.h"
#include "i18n.h" #include "i18n.h"
#define MAX_UNK_CACHE_ENTRIES 1000 /* we use a linked list - so I guess #define MAX_UNK_CACHE_ENTRIES 1000 /* we use a linked list - so I guess
@ -832,6 +833,34 @@ get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint,
/****************
* Search for a key with the given lid and return the complete keyblock
*/
int
get_keyblock_bylid( KBNODE *ret_keyblock, ulong lid )
{
int rc;
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
struct getkey_ctx_s ctx;
u32 kid[2];
if( keyid_from_lid( lid, kid ) )
kid[0] = kid[1] = 0;
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = 12;
ctx.items[0].keyid[0] = kid[0];
ctx.items[0].keyid[1] = kid[1];
rc = lookup_pk( &ctx, pk, ret_keyblock );
get_pubkey_end( &ctx );
free_public_key( pk );
return rc;
}
/**************** /****************

View File

@ -144,6 +144,7 @@ int get_pubkey_byfprint( PKT_public_key *pk, const byte *fprint,
size_t fprint_len ); size_t fprint_len );
int get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint, int get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint,
size_t fprint_len ); size_t fprint_len );
int get_keyblock_bylid( KBNODE *ret_keyblock, ulong lid );
int seckey_available( u32 *keyid ); int seckey_available( u32 *keyid );
int get_seckey_byname( PKT_secret_key *sk, const char *name, int unlock ); int get_seckey_byname( PKT_secret_key *sk, const char *name, int unlock );
int get_seckey_bynames( GETKEY_CTX *rx, PKT_secret_key *sk, int get_seckey_bynames( GETKEY_CTX *rx, PKT_secret_key *sk,

View File

@ -182,6 +182,14 @@ proc_pubkey_enc( CTX c, PACKET *pkt )
* function to check it. */ * function to check it. */
if( opt.verbose ) if( opt.verbose )
log_info(_("public key is %08lX\n"), (ulong)enc->keyid[1] ); log_info(_("public key is %08lX\n"), (ulong)enc->keyid[1] );
if( is_status_enabled() ) {
char buf[50];
sprintf(buf, "%08lX%08lX", (ulong)enc->keyid[0], (ulong)enc->keyid[1]);
write_status_text( STATUS_ENC_TO, buf );
}
if( is_ELGAMAL(enc->pubkey_algo) if( is_ELGAMAL(enc->pubkey_algo)
|| enc->pubkey_algo == PUBKEY_ALGO_DSA || enc->pubkey_algo == PUBKEY_ALGO_DSA
|| is_RSA(enc->pubkey_algo) ) { || is_RSA(enc->pubkey_algo) ) {
@ -914,7 +922,11 @@ check_sig_and_print( CTX c, KBNODE node )
g10_exit(1); g10_exit(1);
} }
else { else {
write_status( STATUS_ERRSIG ); char buf[50];
sprintf(buf, "%08lX%08lX %d",
(ulong)sig->keyid[0], (ulong)sig->keyid[1],
sig->pubkey_algo );
write_status_text( STATUS_ERRSIG, buf );
log_error(_("Can't check signature: %s\n"), g10_errstr(rc) ); log_error(_("Can't check signature: %s\n"), g10_errstr(rc) );
} }
return rc; return rc;

View File

@ -133,6 +133,16 @@ passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode )
:DEFAULT_DIGEST_ALGO; :DEFAULT_DIGEST_ALGO;
} }
if( keyid && !next_pw && is_status_enabled() ) {
char buf[50];
sprintf( buf, "%08lX%08lX", (ulong)keyid[0], (ulong)keyid[1] );
if( keyid[2] && keyid[3] && keyid[0] != keyid[2]
&& keyid[1] != keyid[3] )
sprintf( buf+strlen(buf), " %08lX%08lX",
(ulong)keyid[2], (ulong)keyid[3] );
write_status_text( STATUS_NEED_PASSPHRASE, buf );
}
if( keyid && !opt.batch && !next_pw ) { if( keyid && !opt.batch && !next_pw ) {
PKT_public_key *pk = m_alloc_clear( sizeof *pk ); PKT_public_key *pk = m_alloc_clear( sizeof *pk );
size_t n; size_t n;
@ -159,15 +169,6 @@ passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode )
tty_printf("\n"); tty_printf("\n");
free_public_key( pk ); free_public_key( pk );
} }
else if( keyid && !next_pw ) {
char buf[50];
sprintf( buf, "%08lX%08lX", (ulong)keyid[0], (ulong)keyid[1] );
if( keyid[2] && keyid[3] && keyid[0] != keyid[2]
&& keyid[1] != keyid[3] )
sprintf( buf+strlen(buf), " %08lX%08lX",
(ulong)keyid[2], (ulong)keyid[3] );
write_status_text( STATUS_NEED_PASSPHRASE, buf );
}
if( next_pw ) { if( next_pw ) {
pw = next_pw; pw = next_pw;

View File

@ -107,8 +107,8 @@ show_paths( ulong lid, int only_first )
/**************** /****************
* Returns true if an ownertrust has changed. * Returns true if an ownertrust has changed.
*/ */
int static int
edit_ownertrust( ulong lid, int mode ) do_edit_ownertrust( ulong lid, int mode, unsigned *new_trust )
{ {
char *p; char *p;
int rc; int rc;
@ -117,6 +117,7 @@ edit_ownertrust( ulong lid, int mode )
PKT_public_key *pk ; PKT_public_key *pk ;
int changed=0; int changed=0;
int quit=0; int quit=0;
int show=0;
rc = keyid_from_lid( lid, keyid ); rc = keyid_from_lid( lid, keyid );
if( rc ) { if( rc ) {
@ -177,14 +178,15 @@ edit_ownertrust( ulong lid, int mode )
case '4': trust = TRUST_FULLY ; break; case '4': trust = TRUST_FULLY ; break;
default: BUG(); default: BUG();
} }
if( !update_ownertrust( lid, trust ) ) *new_trust = trust;
changed++; changed = 1;
break; break;
} }
else if( *p == ans[0] || *p == ans[1] ) { else if( *p == ans[0] || *p == ans[1] ) {
tty_printf(_( tty_printf(_(
"Certificates leading to an ultimately trusted key:\n")); "Certificates leading to an ultimately trusted key:\n"));
show_paths( lid, 1 ); show = 1;
break;
} }
else if( mode && (*p == ans[2] || *p == ans[3] || *p == CONTROL_D ) ) { else if( mode && (*p == ans[2] || *p == ans[3] || *p == CONTROL_D ) ) {
break ; /* back to the menu */ break ; /* back to the menu */
@ -197,73 +199,71 @@ edit_ownertrust( ulong lid, int mode )
} }
m_free(p); m_free(p);
m_free(pk); m_free(pk);
return quit? -1 : changed; return show? -2: quit? -1 : changed;
} }
int
edit_ownertrust( ulong lid, int mode )
{
unsigned trust;
for(;;) {
switch( do_edit_ownertrust( lid, mode, &trust ) ) {
case -1:
return 0;
case -2:
show_paths( lid, 1 );
break;
case 1:
if( !update_ownertrust( lid, trust ) )
return 1;
return 0;
default:
return 0;
}
}
}
static int
add_ownertrust_cb( ulong lid )
{
unsigned trust;
int rc = do_edit_ownertrust( lid, 0, &trust );
if( rc == 1 )
return trust & TRUST_MASK;
return rc > 0? 0 : rc;
}
/**************** /****************
* Try to add some more owner trusts (interactive) * Try to add some more owner trusts (interactive)
* This function presents all the signator in a certificate * This function presents all the signator in a certificate
* chain who have no trust value assigned. * chain who have no ownertrust value assigned.
* Returns: -1 if no ownertrust were added. * Returns: -1 if no ownertrust were added.
*/ */
static int static int
add_ownertrust( PKT_public_key *pk, int *quit ) add_ownertrust( PKT_public_key *pk, int *quit, unsigned *trustlevel )
{ {
int rc; int rc;
void *context = NULL; unsigned flags = 0;
ulong lid;
unsigned otrust, validity;
int any=0, changed=0, any_undefined=0;
*quit = 0; *quit = 0;
*trustlevel = 0;
tty_printf( tty_printf(
_("Could not find a valid trust path to the key. Let's see whether we\n" _("Could not find a valid trust path to the key. Let's see whether we\n"
"can assign some missing owner trust values.\n\n")); "can assign some missing owner trust values.\n\n"));
rc = query_trust_record( pk ); rc = check_trust( pk, trustlevel, NULL, add_ownertrust_cb, &flags );
if( rc ) {
log_error("Ooops: not in trustdb\n");
return -1;
}
lid = pk->local_id; if( !(flags & 1) )
while( enum_cert_paths( &context, &lid, &otrust, &validity ) != -1 ) {
if( lid == pk->local_id )
continue;
any=1;
if( changed ) {
/* because enum_cert_paths() makes a snapshop of the
* trust paths, the otrust and validity are not anymore
* valid after changing an entry - we have to reread
* those values from then on
*/
otrust = get_ownertrust( lid );
/* fixme: and the validity? */
}
if( otrust == TRUST_UNDEFINED ) {
any_undefined=1;
enum_cert_paths_print( &context, NULL, changed, lid );
tty_printf("\n");
rc = edit_ownertrust( lid, 0 );
if( rc == -1 ) {
*quit = 1;
break;
}
else if( rc > 0 )
changed = 1;
}
}
enum_cert_paths( &context, NULL, NULL, NULL ); /* release context */
if( !any )
tty_printf(_("No path leading to one of our keys found.\n\n") ); tty_printf(_("No path leading to one of our keys found.\n\n") );
else if( !any_undefined ) else if( !(flags & 2) )
tty_printf(_("No certificates with undefined trust found.\n\n") ); tty_printf(_("No certificates with undefined trust found.\n\n") );
else if( !changed ) else if( !(flags & 4) )
tty_printf(_("No trust values changed.\n\n") ); tty_printf(_("No trust values changed.\n\n") );
return changed? 0:-1; return (flags & 4)? 0:-1;
} }
/**************** /****************
@ -274,7 +274,9 @@ static int
do_we_trust( PKT_public_key *pk, int trustlevel ) do_we_trust( PKT_public_key *pk, int trustlevel )
{ {
int rc; int rc;
int did_add = 0;
retry:
if( (trustlevel & TRUST_FLAG_REVOKED) ) { if( (trustlevel & TRUST_FLAG_REVOKED) ) {
log_info(_("key %08lX: key has been revoked!\n"), log_info(_("key %08lX: key has been revoked!\n"),
(ulong)keyid_from_pk( pk, NULL) ); (ulong)keyid_from_pk( pk, NULL) );
@ -295,7 +297,7 @@ do_we_trust( PKT_public_key *pk, int trustlevel )
g10_errstr(rc) ); g10_errstr(rc) );
return 0; /* no */ return 0; /* no */
} }
rc = check_trust( pk, &trustlevel, NULL ); rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
if( rc ) if( rc )
log_fatal("trust check after insert failed: %s\n", log_fatal("trust check after insert failed: %s\n",
g10_errstr(rc) ); g10_errstr(rc) );
@ -317,14 +319,10 @@ do_we_trust( PKT_public_key *pk, int trustlevel )
else { else {
int quit; int quit;
rc = add_ownertrust( pk, &quit ); rc = add_ownertrust( pk, &quit, &trustlevel );
if( !rc && !quit ) { if( !rc && !did_add && !quit ) {
rc = check_trust( pk, &trustlevel, NULL ); did_add = 1;
if( rc ) goto retry;
log_fatal("trust check after add_ownertrust failed: %s\n",
g10_errstr(rc) );
/* fixme: this is recursive; we should unroll it */
return do_we_trust( pk, trustlevel );
} }
} }
return 0; return 0;
@ -353,10 +351,6 @@ do_we_trust( PKT_public_key *pk, int trustlevel )
default: BUG(); default: BUG();
} }
/* Eventuell fragen falls der trustlevel nicht ausreichend ist */
return 1; /* yes */ return 1; /* yes */
} }
@ -419,7 +413,7 @@ check_signatures_trust( PKT_signature *sig )
{ {
PKT_public_key *pk = m_alloc_clear( sizeof *pk ); PKT_public_key *pk = m_alloc_clear( sizeof *pk );
int trustlevel; int trustlevel;
int dont_try = 0; int did_add = 0;
int rc=0; int rc=0;
rc = get_pubkey( pk, sig->keyid ); rc = get_pubkey( pk, sig->keyid );
@ -429,13 +423,13 @@ check_signatures_trust( PKT_signature *sig )
goto leave; goto leave;
} }
retry: rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
rc = check_trust( pk, &trustlevel, NULL );
if( rc ) { if( rc ) {
log_error("check trust failed: %s\n", g10_errstr(rc)); log_error("check trust failed: %s\n", g10_errstr(rc));
goto leave; goto leave;
} }
retry:
if( (trustlevel & TRUST_FLAG_REVOKED) ) { if( (trustlevel & TRUST_FLAG_REVOKED) ) {
write_status( STATUS_KEYREVOKED ); write_status( STATUS_KEYREVOKED );
log_info(_("WARNING: This key has been revoked by its owner!\n")); log_info(_("WARNING: This key has been revoked by its owner!\n"));
@ -451,7 +445,7 @@ check_signatures_trust( PKT_signature *sig )
g10_errstr(rc) ); g10_errstr(rc) );
goto leave; goto leave;
} }
rc = check_trust( pk, &trustlevel, NULL ); rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
if( rc ) if( rc )
log_fatal("trust check after insert failed: %s\n", log_fatal("trust check after insert failed: %s\n",
g10_errstr(rc) ); g10_errstr(rc) );
@ -464,7 +458,7 @@ check_signatures_trust( PKT_signature *sig )
break; break;
case TRUST_UNDEFINED: case TRUST_UNDEFINED:
if( dont_try || opt.batch || opt.answer_no ) { if( did_add || opt.batch || opt.answer_no ) {
write_status( STATUS_TRUST_UNDEFINED ); write_status( STATUS_TRUST_UNDEFINED );
log_info(_( log_info(_(
"WARNING: This key is not certified with a trusted signature!\n")); "WARNING: This key is not certified with a trusted signature!\n"));
@ -474,9 +468,9 @@ check_signatures_trust( PKT_signature *sig )
} }
else { else {
int quit; int quit;
rc = add_ownertrust( pk, &quit ); rc = add_ownertrust( pk, &quit, &trustlevel );
if( rc || quit ) { if( rc || quit ) {
dont_try = 1; did_add = 1;
rc = 0; rc = 0;
} }
goto retry; goto retry;
@ -591,7 +585,7 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) { else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) {
int trustlevel; int trustlevel;
rc = check_trust( pk, &trustlevel, NULL ); rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
if( rc ) { if( rc ) {
log_error("error checking pk of `%s': %s\n", log_error("error checking pk of `%s': %s\n",
answer, g10_errstr(rc) ); answer, g10_errstr(rc) );
@ -630,7 +624,7 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) { else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) {
int trustlevel; int trustlevel;
rc = check_trust( pk, &trustlevel, NULL ); rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
if( rc ) { if( rc ) {
free_public_key( pk ); pk = NULL; free_public_key( pk ); pk = NULL;
log_error(_("%s: error checking key: %s\n"), log_error(_("%s: error checking key: %s\n"),

View File

@ -32,6 +32,7 @@
#include "main.h" #include "main.h"
#include "options.h" #include "options.h"
#include "i18n.h" #include "i18n.h"
#include "status.h"
static int static int
@ -175,6 +176,14 @@ check_secret_key( PKT_secret_key *sk, int n )
if( i ) if( i )
log_info(_("Invalid passphrase; please try again ...\n")); log_info(_("Invalid passphrase; please try again ...\n"));
rc = do_check( sk ); rc = do_check( sk );
if( rc == G10ERR_BAD_PASS && is_status_enabled() ) {
u32 kid[2];
char buf[50];
keyid_from_sk( sk, kid );
sprintf(buf, "%08lX%08lX", (ulong)kid[0], (ulong)kid[1]);
write_status_text( STATUS_BAD_PASSPHRASE, buf );
}
if( have_static_passphrase() ) if( have_static_passphrase() )
break; break;
} }

View File

@ -99,6 +99,11 @@ write_status_text ( int no, const char *text)
case STATUS_NEED_PASSPHRASE: s = "NEED_PASSPHRASE\n"; break; case STATUS_NEED_PASSPHRASE: s = "NEED_PASSPHRASE\n"; break;
case STATUS_VALIDSIG : s = "VALIDSIG\n"; break; case STATUS_VALIDSIG : s = "VALIDSIG\n"; break;
case STATUS_SIG_ID : s = "SIG_ID\n"; break; case STATUS_SIG_ID : s = "SIG_ID\n"; break;
case STATUS_ENC_TO : s = "ENC_TO\n"; break;
case STATUS_NODATA : s = "NODATA\n"; break;
case STATUS_BAD_PASSPHRASE : s = "BAD_PASSPHRASE\n"; break;
case STATUS_NO_PUBKEY : s = "NO_PUBKEY\n"; break;
case STATUS_NO_SECKEY : s = "NO_SECKEY\n"; break;
default: s = "?\n"; break; default: s = "?\n"; break;
} }

View File

@ -50,6 +50,11 @@
#define STATUS_NEED_PASSPHRASE 20 #define STATUS_NEED_PASSPHRASE 20
#define STATUS_VALIDSIG 21 #define STATUS_VALIDSIG 21
#define STATUS_SIG_ID 22 #define STATUS_SIG_ID 22
#define STATUS_ENC_TO 23
#define STATUS_NODATA 24
#define STATUS_BAD_PASSPHRASE 25
#define STATUS_NO_PUBKEY 26
#define STATUS_NO_SECKEY 27
/*-- status.c --*/ /*-- status.c --*/
void set_status_fd ( int fd ); void set_status_fd ( int fd );

View File

@ -633,12 +633,15 @@ tdbio_read_modify_stamp( int modify_down )
} }
void void
tdbio_write_modify_stamp( int down, int up ) tdbio_write_modify_stamp( int up, int down )
{ {
TRUSTREC vr; TRUSTREC vr;
int rc; int rc;
ulong stamp; ulong stamp;
if( !(up || down) )
return;
rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc ) if( rc )
log_fatal( _("%s: error reading version record: %s\n"), log_fatal( _("%s: error reading version record: %s\n"),
@ -651,7 +654,7 @@ tdbio_write_modify_stamp( int down, int up )
vr.r.ver.mod_up = stamp; vr.r.ver.mod_up = stamp;
rc = tdbio_write_record( &vr ); rc = tdbio_write_record( &vr );
if( !rc ) if( rc )
log_fatal( _("%s: error writing version record: %s\n"), log_fatal( _("%s: error writing version record: %s\n"),
db_name, g10_errstr(rc) ); db_name, g10_errstr(rc) );
} }

View File

@ -176,7 +176,7 @@ int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected );
int tdbio_write_record( TRUSTREC *rec ); int tdbio_write_record( TRUSTREC *rec );
int tdbio_db_matches_options(void); int tdbio_db_matches_options(void);
ulong tdbio_read_modify_stamp( int modify_down ); ulong tdbio_read_modify_stamp( int modify_down );
void tdbio_write_modify_stamp( int down, int up ); void tdbio_write_modify_stamp( int up, int down );
int tdbio_is_dirty(void); int tdbio_is_dirty(void);
int tdbio_sync(void); int tdbio_sync(void);
int tdbio_begin_transaction(void); int tdbio_begin_transaction(void);

View File

@ -41,6 +41,7 @@
#include "main.h" #include "main.h"
#include "i18n.h" #include "i18n.h"
#include "tdbio.h" #include "tdbio.h"
#include "ttyio.h"
#if MAX_FINGERPRINT_LEN > 20 #if MAX_FINGERPRINT_LEN > 20
#error Must change structure of trustdb #error Must change structure of trustdb
@ -115,16 +116,20 @@ static int ins_lid_table_item( LOCAL_ID_TABLE tbl, ulong lid, unsigned flag );
static int qry_lid_table_flag( LOCAL_ID_TABLE tbl, ulong lid, unsigned *flag ); static int qry_lid_table_flag( LOCAL_ID_TABLE tbl, ulong lid, unsigned *flag );
static void propagate_validity( TN node ); static int propagate_validity( TN root, TN node,
int (*add_fnc)(ulong), unsigned *retflgs );
static void print_user_id( const char *text, u32 *keyid ); static void print_user_id( FILE *fp, const char *text, u32 *keyid );
static int do_check( TRUSTREC *drec, unsigned *trustlevel, const char *nhash); static int do_check( TRUSTREC *drec, unsigned *trustlevel,
const char *nhash, int (*add_fnc)(ulong),
unsigned *retflgs);
static int get_dir_record( PKT_public_key *pk, TRUSTREC *rec ); static int get_dir_record( PKT_public_key *pk, TRUSTREC *rec );
static void upd_pref_record( TRUSTREC *urec, u32 *keyid, PKT_signature *sig ); static void upd_pref_record( TRUSTREC *urec, u32 *keyid, PKT_signature *sig );
static void upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid, static void upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
TRUSTREC *drec, RECNO_LIST *recno_list, int recheck, TRUSTREC *drec, RECNO_LIST *recno_list, int recheck,
TRUSTREC *urec, const byte *uidhash, int revoked ); TRUSTREC *urec, const byte *uidhash, int revoked,
int *mod_up, int *mod_down );
/* a table used to keep track of ultimately trusted keys /* a table used to keep track of ultimately trusted keys
* which are the ones from our secrings and the trusted keys */ * which are the ones from our secrings and the trusted keys */
@ -375,6 +380,7 @@ keyid_from_lid( ulong lid, u32 *keyid )
int rc; int rc;
init_trustdb(); init_trustdb();
keyid[0] = keyid[1] = 0;
rc = tdbio_read_record( lid, &rec, 0 ); rc = tdbio_read_record( lid, &rec, 0 );
if( rc ) { if( rc ) {
log_error(_("error reading dir record for LID %lu: %s\n"), log_error(_("error reading dir record for LID %lu: %s\n"),
@ -622,20 +628,23 @@ init_trustdb()
************* Print helpers **************** ************* Print helpers ****************
***********************************************/ ***********************************************/
static void static void
print_user_id( const char *text, u32 *keyid ) print_user_id( FILE *fp, const char *text, u32 *keyid )
{ {
char *p; char *p;
size_t n; size_t n;
p = get_user_id( keyid, &n ); p = get_user_id( keyid, &n );
if( *text ) { if( fp ) {
fputs( text, stdout); fprintf( fp, "%s \"", text );
putchar(' '); print_string( fp, p, n, 0 );
putc('\"', fp);
putc('\n', fp);
}
else {
tty_printf( "%s \"", text );
tty_print_string( p, n );
tty_printf( "\"\n" );
} }
putchar('\"');
print_string( stdout, p, n, 0 );
putchar('\"');
putchar('\n');
m_free(p); m_free(p);
} }
@ -699,35 +708,122 @@ print_path( int pathlen, TN ME .........., FILE *fp, ulong highlight )
static void static void
print_default_uid( ulong lid ) print_default_uid( FILE *fp, ulong lid )
{ {
u32 keyid[2]; u32 keyid[2];
if( !keyid_from_lid( lid, keyid ) ) if( !keyid_from_lid( lid, keyid ) )
print_user_id( "", keyid ); print_user_id( fp, "", keyid );
} }
static void static void
dump_tn_tree( int indent, TN tree ) print_uid_from_keyblock( FILE *fp, KBNODE keyblock, ulong urecno )
{
TRUSTREC urec;
KBNODE node;
byte uhash[20];
read_record( urecno, &urec, RECTYPE_UID );
for( node=keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID ) {
PKT_user_id *uidpkt = node->pkt->pkt.user_id;
rmd160_hash_buffer( uhash, uidpkt->name, uidpkt->len );
if( !memcmp( uhash, urec.r.uid.namehash, 20 ) ) {
print_string( fp, uidpkt->name, uidpkt->len, ':' );
return;
}
}
}
fputs("[?]", fp );
}
static void
dump_tn_tree( FILE *fp, int level, TN tree )
{ {
TN kr, ur; TN kr, ur;
for( kr=tree; kr; kr = kr->next ) { for( kr=tree; kr; kr = kr->next ) {
printf("%*s", indent*4, "" ); if( fp ) {
printf("K%lu(ot=%d,val=%d) ", kr->lid, fprintf( fp, "%*s", level*4, "" );
fprintf( fp, "K%lu(ot=%d,val=%d) ", kr->lid,
kr->n.k.ownertrust, kr->n.k.ownertrust,
kr->n.k.validity ); kr->n.k.validity );
print_default_uid( kr->lid ); }
else {
tty_printf("%*s", level*4, "" );
tty_printf("K%lu(ot=%d,val=%d) ", kr->lid,
kr->n.k.ownertrust,
kr->n.k.validity );
}
print_default_uid( fp, kr->lid );
for( ur=kr->list; ur; ur = ur->next ) { for( ur=kr->list; ur; ur = ur->next ) {
printf("%*s ", indent*4, "" ); if( fp ) {
printf("U%lu(mc=%d,fc=%d,val=%d)\n", ur->lid, fprintf(fp, "%*s ", level*4, "" );
fprintf(fp, "U%lu(mc=%d,fc=%d,val=%d)\n", ur->lid,
ur->n.u.marginal_count, ur->n.u.marginal_count,
ur->n.u.fully_count, ur->n.u.fully_count,
ur->n.u.validity ur->n.u.validity
); );
dump_tn_tree( indent+1, ur->list );
} }
else {
tty_printf("%*s ", level*4, "" );
tty_printf("U%lu(mc=%d,fc=%d,val=%d)\n", ur->lid,
ur->n.u.marginal_count,
ur->n.u.fully_count,
ur->n.u.validity
);
}
dump_tn_tree( fp, level+1, ur->list );
}
}
}
/****************
* Special version of dump_tn_tree, which prints it colon delimited.
* Format:
* level:keyid:type:recno:ot:val:mc:cc:name:
* With TYPE = U for a user ID
* K for a key
* The RECNO is either the one of the dir record or the one of the uid record.
* OT is the the usual trust letter and only availabel on K lines.
* VAL is the calcualted validity
* MC is the marginal trust counter and only available on U lines
* CC is the same for the complete count
* NAME ist the username and only printed on U lines
*/
static void
dump_tn_tree_with_colons( int level, TN tree )
{
TN kr, ur;
for( kr=tree; kr; kr = kr->next ) {
KBNODE kb = NULL;
u32 kid[2];
keyid_from_lid( kr->lid, kid );
get_keyblock_bylid( &kb, kr->lid );
printf( "%d:%08lX%08lX:K:%lu:%c:%c::::\n",
level, (ulong)kid[0], (ulong)kid[1], kr->lid,
trust_letter( kr->n.k.ownertrust ),
trust_letter( kr->n.k.validity ) );
for( ur=kr->list; ur; ur = ur->next ) {
printf( "%d:%08lX%08lX:U:%lu::%c:%d:%d:",
level, (ulong)kid[0], (ulong)kid[1], ur->lid,
trust_letter( kr->n.u.validity ),
ur->n.u.marginal_count,
ur->n.u.fully_count );
print_uid_from_keyblock( stdout, kb, ur->lid );
putchar(':');
putchar('\n');
dump_tn_tree_with_colons( level+1, ur->list );
}
release_kbnode( kb );
} }
} }
@ -851,6 +947,7 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash,
* Process a hintlist. * Process a hintlist.
* Fixme: this list is not anymore anchored to another * Fixme: this list is not anymore anchored to another
* record, so it should be put elsewehere in case of an error * record, so it should be put elsewehere in case of an error
* FIXME: add mod_up/down handling
*/ */
static void static void
process_hintlist( ulong hintlist, ulong hint_owner ) process_hintlist( ulong hintlist, ulong hint_owner )
@ -1184,7 +1281,8 @@ upd_key_record( KBNODE keyblock, KBNODE keynode, u32 *keyid,
*/ */
static void static void
upd_uid_record( KBNODE keyblock, KBNODE uidnode, u32 *keyid, upd_uid_record( KBNODE keyblock, KBNODE uidnode, u32 *keyid,
TRUSTREC *drec, RECNO_LIST *recno_list, int recheck ) TRUSTREC *drec, RECNO_LIST *recno_list,
int recheck, int *mod_up, int *mod_down )
{ {
ulong lid = drec->recnum; ulong lid = drec->recnum;
PKT_user_id *uid = uidnode->pkt->pkt.user_id; PKT_user_id *uid = uidnode->pkt->pkt.user_id;
@ -1327,10 +1425,10 @@ upd_uid_record( KBNODE keyblock, KBNODE uidnode, u32 *keyid,
write_record( &urec ); write_record( &urec );
if( !( urec.r.uid.uidflags & UIDF_VALID ) if( !( urec.r.uid.uidflags & UIDF_VALID )
|| ( urec.r.uid.uidflags & UIDF_REVOKED ) ) || ( urec.r.uid.uidflags & UIDF_REVOKED ) )
; /*FIXME: mark as modified down */ *mod_down=1;
else else
; /*FIXME: mark as modified up (maybe a new uuser id)*/ *mod_up=1; /*(maybe a new user id)*/
/* Hmmm, did we catch changed expiration dates? */
} }
} /* end check self-signatures */ } /* end check self-signatures */
@ -1362,11 +1460,11 @@ upd_uid_record( KBNODE keyblock, KBNODE uidnode, u32 *keyid,
if( (sig->sig_class&~3) == 0x10 ) { /* regular certification */ if( (sig->sig_class&~3) == 0x10 ) { /* regular certification */
upd_cert_record( keyblock, node, keyid, drec, recno_list, upd_cert_record( keyblock, node, keyid, drec, recno_list,
recheck, &urec, uidhash, 0 ); recheck, &urec, uidhash, 0, mod_up, mod_down );
} }
else if( sig->sig_class == 0x30 ) { /* cert revocation */ else if( sig->sig_class == 0x30 ) { /* cert revocation */
upd_cert_record( keyblock, node, keyid, drec, recno_list, upd_cert_record( keyblock, node, keyid, drec, recno_list,
recheck, &urec, uidhash, 1 ); recheck, &urec, uidhash, 1, mod_up, mod_down );
} }
} /* end check certificates */ } /* end check certificates */
@ -1490,11 +1588,11 @@ upd_pref_record( TRUSTREC *urec, u32 *keyid, PKT_signature *sig )
} }
/* FIXME: add logic to set the modify_{down,up} */
static void static void
upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid, upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
TRUSTREC *drec, RECNO_LIST *recno_list, int recheck, TRUSTREC *drec, RECNO_LIST *recno_list, int recheck,
TRUSTREC *urec, const byte *uidhash, int revoked ) TRUSTREC *urec, const byte *uidhash, int revoked,
int *mod_up, int *mod_down )
{ {
/* We simply insert the signature into the sig records but /* We simply insert the signature into the sig records but
* avoid duplicate ones. We do not check them here because * avoid duplicate ones. We do not check them here because
@ -1577,8 +1675,12 @@ upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
revoked? _("Valid certificate revocation") revoked? _("Valid certificate revocation")
: _("Good certificate") ); : _("Good certificate") );
rec.r.sig.sig[i].flag = SIGF_CHECKED | SIGF_VALID; rec.r.sig.sig[i].flag = SIGF_CHECKED | SIGF_VALID;
if( revoked ) /* we are investigating revocations */ if( revoked ) { /* we are investigating revocations */
rec.r.sig.sig[i].flag |= SIGF_REVOKED; rec.r.sig.sig[i].flag |= SIGF_REVOKED;
*mod_down = 1;
}
else
*mod_up = 1;
} }
else if( rc == G10ERR_NO_PUBKEY ) { else if( rc == G10ERR_NO_PUBKEY ) {
/* This may happen if the key is still in the trustdb /* This may happen if the key is still in the trustdb
@ -1589,6 +1691,7 @@ upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
uidhash[19], (ulong)sig->keyid[1], uidhash[19], (ulong)sig->keyid[1],
_("public key not anymore available") ); _("public key not anymore available") );
rec.r.sig.sig[i].flag = SIGF_NOPUBKEY; rec.r.sig.sig[i].flag = SIGF_NOPUBKEY;
*mod_down = 1;
if( revoked ) if( revoked )
rec.r.sig.sig[i].flag |= SIGF_REVOKED; rec.r.sig.sig[i].flag |= SIGF_REVOKED;
} }
@ -1600,8 +1703,10 @@ upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
: _("Invalid certificate"), : _("Invalid certificate"),
g10_errstr(rc)); g10_errstr(rc));
rec.r.sig.sig[i].flag = SIGF_CHECKED; rec.r.sig.sig[i].flag = SIGF_CHECKED;
if( revoked ) if( revoked ) {
rec.r.sig.sig[i].flag |= SIGF_REVOKED; rec.r.sig.sig[i].flag |= SIGF_REVOKED;
*mod_down = 1;
}
} }
rec.dirty = 1; rec.dirty = 1;
} }
@ -1662,8 +1767,12 @@ upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
: _("Good certificate") ); : _("Good certificate") );
newlid = pk_lid; /* this is the pk of the signature */ newlid = pk_lid; /* this is the pk of the signature */
newflag = SIGF_CHECKED | SIGF_VALID; newflag = SIGF_CHECKED | SIGF_VALID;
if( revoked ) if( revoked ) {
newflag |= SIGF_REVOKED; newflag |= SIGF_REVOKED;
*mod_down = 1;
}
else
*mod_up = 1;
} }
else if( rc == G10ERR_NO_PUBKEY ) { else if( rc == G10ERR_NO_PUBKEY ) {
if( opt.verbose > 1 || DBG_TRUST ) if( opt.verbose > 1 || DBG_TRUST )
@ -1686,6 +1795,7 @@ upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
newflag = SIGF_CHECKED; newflag = SIGF_CHECKED;
if( revoked ) if( revoked )
newflag |= SIGF_REVOKED; newflag |= SIGF_REVOKED;
*mod_down = 1;
} }
if( delrec.recnum ) { /* we can reuse an unused slot */ if( delrec.recnum ) { /* we can reuse an unused slot */
@ -1730,6 +1840,8 @@ update_trust_record( KBNODE keyblock, int recheck, int *modified )
int rc = 0; int rc = 0;
u32 keyid[2]; /* keyid of primary key */ u32 keyid[2]; /* keyid of primary key */
ulong recno, lastrecno; ulong recno, lastrecno;
int mod_up = 0;
int mod_down = 0;
RECNO_LIST recno_list = NULL; /* list of verified records */ RECNO_LIST recno_list = NULL; /* list of verified records */
/* fixme: replace recno_list by a lookup on node->recno */ /* fixme: replace recno_list by a lookup on node->recno */
@ -1767,7 +1879,7 @@ update_trust_record( KBNODE keyblock, int recheck, int *modified )
for( node=keyblock; node; node = node->next ) { for( node=keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID ) if( node->pkt->pkttype == PKT_USER_ID )
upd_uid_record( keyblock, node, keyid, upd_uid_record( keyblock, node, keyid,
&drec, &recno_list, recheck ); &drec, &recno_list, recheck, &mod_up, &mod_down );
} }
/* delete keyrecords from the trustdb which are not anymore used */ /* delete keyrecords from the trustdb which are not anymore used */
@ -1842,6 +1954,7 @@ update_trust_record( KBNODE keyblock, int recheck, int *modified )
drec.r.dir.dirflags |= DIRF_CHECKED; drec.r.dir.dirflags |= DIRF_CHECKED;
drec.r.dir.valcheck = 0; drec.r.dir.valcheck = 0;
write_record( &drec ); write_record( &drec );
tdbio_write_modify_stamp( mod_up, mod_down );
rc = tdbio_end_transaction(); rc = tdbio_end_transaction();
} }
rel_recno_list( &recno_list ); rel_recno_list( &recno_list );
@ -1854,7 +1967,7 @@ update_trust_record( KBNODE keyblock, int recheck, int *modified )
* This function assumes that the record does not yet exist. * This function assumes that the record does not yet exist.
*/ */
int int
insert_trust_record( PKT_public_key *pk ) insert_trust_record( PKT_public_key *orig_pk )
{ {
TRUSTREC dirrec; TRUSTREC dirrec;
TRUSTREC shadow; TRUSTREC shadow;
@ -1864,6 +1977,7 @@ insert_trust_record( PKT_public_key *pk )
size_t fingerlen; size_t fingerlen;
int rc = 0; int rc = 0;
ulong hintlist = 0; ulong hintlist = 0;
PKT_public_key *pk;
if( opt.dry_run ) if( opt.dry_run )
@ -1871,7 +1985,7 @@ insert_trust_record( PKT_public_key *pk )
init_trustdb(); init_trustdb();
fingerprint_from_pk( pk, fingerprint, &fingerlen ); fingerprint_from_pk( orig_pk, fingerprint, &fingerlen );
/* fixme: assert that we do not have this record. /* fixme: assert that we do not have this record.
* we can do this by searching for the primary keyid * we can do this by searching for the primary keyid
@ -1883,6 +1997,10 @@ insert_trust_record( PKT_public_key *pk )
* to the primary one which has the user ids etc.) * to the primary one which has the user ids etc.)
*/ */
if( orig_pk->local_id )
log_debug("insert_trust_record with pk->local_id=%lu (1)\n",
orig_pk->local_id );
/* get the keyblock which has the key */ /* get the keyblock which has the key */
rc = get_keyblock_byfprint( &keyblock, fingerprint, fingerlen ); rc = get_keyblock_byfprint( &keyblock, fingerprint, fingerlen );
if( rc ) { /* that should never happen */ if( rc ) { /* that should never happen */
@ -1891,32 +2009,18 @@ insert_trust_record( PKT_public_key *pk )
goto leave; goto leave;
} }
/* make sure that we use the primary key */
pk = find_kbnode( keyblock, PKT_PUBLIC_KEY )->pkt->pkt.public_key;
if( pk->local_id ) { if( pk->local_id ) {
log_debug("insert_trust_reord with pk->local_id=%lu\n", pk->local_id ); orig_pk->local_id = pk->local_id;
log_debug("insert_trust_record with pk->local_id=%lu (2)\n",
pk->local_id );
rc = update_trust_record( keyblock, 1, NULL ); rc = update_trust_record( keyblock, 1, NULL );
release_kbnode( keyblock ); release_kbnode( keyblock );
return rc; return rc;
} }
/* check that we used the primary key (we are little bit paranoid) */
{ PKT_public_key *a_pk;
u32 akid[2], bkid[2];
node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
a_pk = node->pkt->pkt.public_key;
/* we can't use cmp_public_keys here because some parts (expiredate)
* might not be set in pk <--- but why (fixme) */
keyid_from_pk( a_pk, akid );
keyid_from_pk( pk, bkid );
if( akid[0] != bkid[0] || akid[1] != bkid[1] ) {
log_error(_("did not use primary key for insert_trust_record()\n"));
rc = G10ERR_GENERAL;
goto leave;
}
}
/* We have to look for a shadow dir record which must be reused /* We have to look for a shadow dir record which must be reused
* as the dir record. And: check all signatures which are listed * as the dir record. And: check all signatures which are listed
* in the hintlist of the shadow dir record. * in the hintlist of the shadow dir record.
@ -1942,6 +2046,7 @@ insert_trust_record( PKT_public_key *pk )
/* out the LID into the keyblock */ /* out the LID into the keyblock */
pk->local_id = dirrec.r.dir.lid; pk->local_id = dirrec.r.dir.lid;
orig_pk->local_id = dirrec.r.dir.lid;
for( node=keyblock; node; node = node->next ) { for( node=keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_PUBLIC_KEY if( node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
@ -1954,7 +2059,8 @@ insert_trust_record( PKT_public_key *pk )
} }
} }
/* FIXME: mark tdb as modified upwards */ /* mark tdb as modified upwards */
tdbio_write_modify_stamp( 1, 0 );
/* and put all the other stuff into the keydb */ /* and put all the other stuff into the keydb */
rc = update_trust_record( keyblock, 1, NULL ); rc = update_trust_record( keyblock, 1, NULL );
@ -2100,9 +2206,57 @@ build_cert_tree( ulong lid, int depth, int max_depth, TN helproot )
} }
static void static void
propagate_validity( TN node ) upd_one_ownertrust( ulong lid, unsigned new_trust, unsigned *retflgs )
{
TRUSTREC rec;
read_record( lid, &rec, RECTYPE_DIR );
if( DBG_TRUST )
log_debug("upd_one_ownertrust of %lu from %u to %u\n",
lid, (unsigned)rec.r.dir.ownertrust, new_trust );
if( retflgs ) {
if( new_trust > rec.r.dir.ownertrust )
*retflgs |= 16; /* modified up */
else
*retflgs |= 32; /* modified down */
}
rec.r.dir.ownertrust = new_trust;
write_record( &rec );
}
/****************
* Update the ownertrust in the complete tree.
*/
static void
propagate_ownertrust( TN kr, ulong lid, unsigned trust )
{
TN ur;
for( ; kr; kr = kr->next ) {
if( kr->lid == lid )
kr->n.k.ownertrust = trust;
for( ur=kr->list; ur; ur = ur->next )
propagate_ownertrust( ur->list, lid, trust );
}
}
/****************
* Calculate the validity of all keys in the tree and especially
* the one of the top key. If add_fnc is not NULL, it is used to
* ask for missing ownertrust values (but only if this will help
* us to increase the validity.
* add_fnc is expected to take the LID of the key under question
* and return a ownertrust value or an error: positive values
* are assumed to be the new ownertrust value; a 0 does mean no change,
* a -1 is a request to cancel this validation procedure, a -2 requests
* a listing of the sub-tree using the tty functions.
*
*
* Returns: 0 = okay
*/
static int
propagate_validity( TN root, TN node, int (*add_fnc)(ulong), unsigned *retflgs )
{ {
TN kr, ur; TN kr, ur;
int max_validity = 0; int max_validity = 0;
@ -2112,7 +2266,9 @@ propagate_validity( TN node )
/* this is one of our keys */ /* this is one of our keys */
assert( !node->list ); /* it should be a leaf */ assert( !node->list ); /* it should be a leaf */
node->n.k.validity = TRUST_ULTIMATE; node->n.k.validity = TRUST_ULTIMATE;
return; if( retflgs )
*retflgs |= 1; /* found a path to an ultimately trusted key */
return 0;
} }
/* loop over all user ids */ /* loop over all user ids */
@ -2120,11 +2276,39 @@ propagate_validity( TN node )
assert( ur->is_uid ); assert( ur->is_uid );
/* loop over all signators */ /* loop over all signators */
for(kr=ur->list; kr; kr = kr->next ) { for(kr=ur->list; kr; kr = kr->next ) {
propagate_validity( kr ); if( propagate_validity( root, kr, add_fnc, retflgs ) )
return -1; /* quit */
if( kr->n.k.validity == TRUST_ULTIMATE ) { if( kr->n.k.validity == TRUST_ULTIMATE ) {
ur->n.u.fully_count = opt.completes_needed; ur->n.u.fully_count = opt.completes_needed;
} }
else if( kr->n.k.validity == TRUST_FULLY ) { else if( kr->n.k.validity == TRUST_FULLY ) {
if( add_fnc && !kr->n.k.ownertrust ) {
int rc;
if( retflgs )
*retflgs |= 2; /* found key with undefined ownertrust*/
do {
rc = add_fnc( kr->lid );
switch( rc ) {
case TRUST_NEVER:
case TRUST_MARGINAL:
case TRUST_FULLY:
propagate_ownertrust( root, kr->lid, rc );
upd_one_ownertrust( kr->lid, rc, retflgs );
if( retflgs )
*retflgs |= 4; /* changed */
break;
case -1:
return -1; /* cancel */
case -2:
dump_tn_tree( NULL, 0, kr );
tty_printf("\n");
break;
default:
break;
}
} while( rc == -2 );
}
if( kr->n.k.ownertrust == TRUST_FULLY ) if( kr->n.k.ownertrust == TRUST_FULLY )
ur->n.u.fully_count++; ur->n.u.fully_count++;
else if( kr->n.k.ownertrust == TRUST_MARGINAL ) else if( kr->n.k.ownertrust == TRUST_MARGINAL )
@ -2145,6 +2329,7 @@ propagate_validity( TN node )
} }
node->n.k.validity = max_validity; node->n.k.validity = max_validity;
return 0;
} }
@ -2155,15 +2340,17 @@ propagate_validity( TN node )
* checking all key signatures up to a some depth. * checking all key signatures up to a some depth.
*/ */
static int static int
verify_key( int max_depth, TRUSTREC *drec, const char *namehash ) verify_key( int max_depth, TRUSTREC *drec, const char *namehash,
int (*add_fnc)(ulong), unsigned *retflgs )
{ {
TN tree; TN tree;
int keytrust; int keytrust;
int pv_result;
tree = build_cert_tree( drec->r.dir.lid, 0, opt.max_cert_depth, NULL ); tree = build_cert_tree( drec->r.dir.lid, 0, opt.max_cert_depth, NULL );
if( !tree ) if( !tree )
return TRUST_UNDEFINED; return TRUST_UNDEFINED;
propagate_validity( tree ); pv_result = propagate_validity( tree, tree, add_fnc, retflgs );
if( namehash ) { if( namehash ) {
/* find the matching user id. /* find the matching user id.
* fixme: the way we handle this is too inefficient */ * fixme: the way we handle this is too inefficient */
@ -2183,7 +2370,8 @@ verify_key( int max_depth, TRUSTREC *drec, const char *namehash )
keytrust = tree->n.k.validity; keytrust = tree->n.k.validity;
/* update the cached validity values */ /* update the cached validity values */
if( keytrust >= TRUST_UNDEFINED if( !pv_result
&& keytrust >= TRUST_UNDEFINED
&& tdbio_db_matches_options() && tdbio_db_matches_options()
&& ( !drec->r.dir.valcheck || drec->r.dir.validity != keytrust ) ) { && ( !drec->r.dir.valcheck || drec->r.dir.validity != keytrust ) ) {
TN ur; TN ur;
@ -2213,7 +2401,8 @@ verify_key( int max_depth, TRUSTREC *drec, const char *namehash )
* but nothing more is known. * but nothing more is known.
*/ */
static int static int
do_check( TRUSTREC *dr, unsigned *validity, const char *namehash ) do_check( TRUSTREC *dr, unsigned *validity,
const char *namehash, int (*add_fnc)(ulong), unsigned *retflgs )
{ {
if( !dr->r.dir.keylist ) { if( !dr->r.dir.keylist ) {
log_error(_("Ooops, no keys\n")); log_error(_("Ooops, no keys\n"));
@ -2224,22 +2413,39 @@ do_check( TRUSTREC *dr, unsigned *validity, const char *namehash )
return G10ERR_TRUSTDB; return G10ERR_TRUSTDB;
} }
if( retflgs )
*retflgs &= ~(16|32); /* reset the 2 special flags */
if( namehash ) { if( namehash ) {
/* Fixme: use the cache */ /* Fixme: use the cache */
*validity = verify_key( opt.max_cert_depth, dr, namehash ); *validity = verify_key( opt.max_cert_depth, dr, namehash,
add_fnc, retflgs );
} }
else if( tdbio_db_matches_options() else if( !add_fnc
&& tdbio_db_matches_options()
&& dr->r.dir.valcheck && dr->r.dir.valcheck
> tdbio_read_modify_stamp( (dr->r.dir.validity < TRUST_FULLY) ) > tdbio_read_modify_stamp( (dr->r.dir.validity < TRUST_FULLY) )
&& dr->r.dir.validity ) && dr->r.dir.validity )
*validity = dr->r.dir.validity; *validity = dr->r.dir.validity;
else else
*validity = verify_key( opt.max_cert_depth, dr, NULL ); *validity = verify_key( opt.max_cert_depth, dr, NULL,
add_fnc, retflgs );
if( !(*validity & TRUST_MASK) )
*validity = TRUST_UNDEFINED;
if( dr->r.dir.dirflags & DIRF_REVOKED ) if( dr->r.dir.dirflags & DIRF_REVOKED )
*validity |= TRUST_FLAG_REVOKED; *validity |= TRUST_FLAG_REVOKED;
/* If we have changed some ownertrusts, set the trustdb timestamps
* and do a sync */
if( retflgs && (*retflgs & (16|32)) ) {
tdbio_write_modify_stamp( (*retflgs & 16), (*retflgs & 32) );
do_sync();
}
return 0; return 0;
} }
@ -2256,6 +2462,9 @@ update_ownertrust( ulong lid, unsigned new_trust )
init_trustdb(); init_trustdb();
read_record( lid, &rec, RECTYPE_DIR ); read_record( lid, &rec, RECTYPE_DIR );
if( DBG_TRUST )
log_debug("update_ownertrust of %lu from %u to %u\n",
lid, (unsigned)rec.r.dir.ownertrust, new_trust );
rec.r.dir.ownertrust = new_trust; rec.r.dir.ownertrust = new_trust;
write_record( &rec ); write_record( &rec );
do_sync(); do_sync();
@ -2512,7 +2721,8 @@ query_trust_record( PKT_public_key *pk )
* is not necessary to check this if we use a local pubring. Hmmmm. * is not necessary to check this if we use a local pubring. Hmmmm.
*/ */
int int
check_trust( PKT_public_key *pk, unsigned *r_trustlevel, const byte *namehash ) check_trust( PKT_public_key *pk, unsigned *r_trustlevel,
const byte *namehash, int (*add_fnc)(ulong), unsigned *retflgs )
{ {
TRUSTREC rec; TRUSTREC rec;
unsigned trustlevel = TRUST_UNKNOWN; unsigned trustlevel = TRUST_UNKNOWN;
@ -2562,7 +2772,7 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel, const byte *namehash )
trustlevel = TRUST_EXPIRED; trustlevel = TRUST_EXPIRED;
} }
else { else {
rc = do_check( &rec, &trustlevel, namehash ); rc = do_check( &rec, &trustlevel, namehash, add_fnc, retflgs );
if( rc ) { if( rc ) {
log_error(_("key %08lX.%lu: trust check failed: %s\n"), log_error(_("key %08lX.%lu: trust check failed: %s\n"),
(ulong)keyid[1], pk->local_id, g10_errstr(rc)); (ulong)keyid[1], pk->local_id, g10_errstr(rc));
@ -2586,7 +2796,7 @@ query_trust_info( PKT_public_key *pk, const byte *namehash )
int c; int c;
init_trustdb(); init_trustdb();
if( check_trust( pk, &trustlevel, namehash ) ) if( check_trust( pk, &trustlevel, namehash, NULL, NULL ) )
return '?'; return '?';
if( trustlevel & TRUST_FLAG_REVOKED ) if( trustlevel & TRUST_FLAG_REVOKED )
return 'r'; return 'r';
@ -2656,12 +2866,15 @@ list_trust_path( const char *username )
tree = build_cert_tree( lid, 0, opt.max_cert_depth, NULL ); tree = build_cert_tree( lid, 0, opt.max_cert_depth, NULL );
if( tree ) if( tree )
propagate_validity( tree ); propagate_validity( tree, tree, NULL, NULL );
dump_tn_tree( 0, tree ); if( opt.with_colons )
printf("(alloced tns=%d max=%d)\n", alloced_tns, max_alloced_tns ); dump_tn_tree_with_colons( 0, tree );
else
dump_tn_tree( stdout, 0, tree );
/*printf("(alloced tns=%d max=%d)\n", alloced_tns, max_alloced_tns );*/
release_tn_tree( tree ); release_tn_tree( tree );
printf("Ownertrust=%c Validity=%c\n", get_ownertrust_info( lid ), /*printf("Ownertrust=%c Validity=%c\n", get_ownertrust_info( lid ),
query_trust_info( pk, NULL ) ); query_trust_info( pk, NULL ) ); */
free_public_key( pk ); free_public_key( pk );

View File

@ -47,7 +47,8 @@ void check_trustdb( const char *username );
void update_trustdb( void ); void update_trustdb( void );
int setup_trustdb( int level, const char *dbname ); int setup_trustdb( int level, const char *dbname );
void init_trustdb( void ); void init_trustdb( void );
int check_trust( PKT_public_key *pk, unsigned *r_trustlevel, const byte* nh ); int check_trust( PKT_public_key *pk, unsigned *r_trustlevel,
const byte* nh, int (*add_fnc)(ulong), unsigned *retflgs );
int query_trust_info( PKT_public_key *pk, const byte *nh ); int query_trust_info( PKT_public_key *pk, const byte *nh );
int enum_cert_paths( void **context, ulong *lid, int enum_cert_paths( void **context, ulong *lid,
unsigned *ownertrust, unsigned *validity ); unsigned *ownertrust, unsigned *validity );

View File

@ -88,6 +88,7 @@ typedef struct {
int g10c_debug_mode; int g10c_debug_mode;
int g10_opt_verbose; int g10_opt_verbose;
const char *g10_opt_homedir;
/*-- dynload.c --*/ /*-- dynload.c --*/
void register_cipher_extension( const char *mainpgm, const char *fname ); void register_cipher_extension( const char *mainpgm, const char *fname );