mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-02 12:01:32 +01:00
See ChangeLog: Wed Mar 17 13:09:03 CET 1999 Werner Koch
This commit is contained in:
parent
dafcce0177
commit
8d255ff264
2
NEWS
2
NEWS
@ -4,6 +4,8 @@
|
||||
|
||||
* 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
|
||||
-----------------------------------
|
||||
|
25
TODO
25
TODO
@ -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.
|
||||
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.
|
||||
|
||||
* 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"
|
||||
|
||||
@ -25,17 +22,11 @@
|
||||
* when decryptiong multiple key: print a warning only if no usable pubkey
|
||||
encrypt package was found. Extension: display a list of all recipients.
|
||||
|
||||
* an ERRSIG argument like
|
||||
ERRSIG <keyid>, where <keyid> is the id of the missing public key
|
||||
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
|
||||
|
||||
|
||||
* Add NO_PUBKEY and NO_SECKEY status lines.
|
||||
* Add more NODATA status lines
|
||||
|
||||
* gpg --keyserver wwwkeys.us.pgp.net --importserver 0x12345678
|
||||
(or --importserver warner@lothar.com, etc)
|
||||
|
||||
|
||||
Nice to have
|
||||
|
252
acinclude.m4
252
acinclude.m4
@ -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.
|
||||
|
@ -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>
|
||||
|
||||
* pubdemo.asc, secdemo.asc: New.
|
||||
|
@ -89,10 +89,11 @@ Enter passphrase: " { sleep 1; send -- "abc\r" }
|
||||
expect {
|
||||
-ex "\r \rRepeat passphrase: " { sleep 1; send -- "abc\r" }
|
||||
timeout { exit 1 } }
|
||||
set timeout 600
|
||||
expect {
|
||||
-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
|
||||
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" {}
|
||||
timeout { exit 1 } }
|
||||
set timeout 600
|
||||
|
@ -13,7 +13,7 @@ test_one () {
|
||||
failed=""
|
||||
|
||||
#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 "SHA1" "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"
|
||||
test_one "RMD160" "9C1185A5C5E9FC54612808977EE8F548B2258D31"
|
||||
@ -25,7 +25,7 @@ fi
|
||||
|
||||
[ "$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 "SHA1" "32D10C7B8CF96570CA04CE37F2A19D84240D3A89"
|
||||
test_one "RMD160" "F71C27109C692C1B56BBDCEB5B9D2865B3708DBC"
|
||||
|
@ -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>
|
||||
|
||||
* dynload.c (DLSYM_NEEDS_UNDERSCORE): Renamed.
|
||||
|
124
cipher/rndegd.c
124
cipher/rndegd.c
@ -34,6 +34,7 @@
|
||||
#include "util.h"
|
||||
#include "ttyio.h"
|
||||
#include "dynload.h"
|
||||
#include "cipher.h"
|
||||
|
||||
#ifdef IS_MODULE
|
||||
#define _(a) (a)
|
||||
@ -64,18 +65,47 @@ do_write( int fd, void *buf, size_t nbytes )
|
||||
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
|
||||
gather_random( void (*add)(const void*, size_t, int), int requester,
|
||||
size_t length, int level )
|
||||
{
|
||||
static int fd = -1;
|
||||
int n;
|
||||
int warn=0;
|
||||
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 ) {
|
||||
const char *name = "/tmp/entropy";
|
||||
char *name = make_filename( g10_opt_homedir, "entropy", NULL );
|
||||
struct sockaddr_un addr;
|
||||
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 )
|
||||
g10_log_fatal("can't connect to `%s': %s\n",
|
||||
name, strerror(errno) );
|
||||
m_free(name);
|
||||
}
|
||||
|
||||
|
||||
while( length ) {
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
int rc;
|
||||
int nbytes;
|
||||
int cmd;
|
||||
do_restart = 0;
|
||||
|
||||
nbytes = length < 255? length : 255;
|
||||
/* send request */
|
||||
cmd = level >= 2 ? 2 : 1;
|
||||
buffer[0] = cmd;
|
||||
/* first time we do it with a non blocking request */
|
||||
buffer[0] = 1; /* non blocking */
|
||||
buffer[1] = nbytes;
|
||||
if( do_write( fd, buffer, 2 ) == -1 )
|
||||
g10_log_fatal("can't write to the EGD: %s\n", strerror(errno) );
|
||||
/* wait on reply */
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(fd, &rfds);
|
||||
tv.tv_sec = 3;
|
||||
tv.tv_usec = 0;
|
||||
if( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) ) {
|
||||
if( !warn )
|
||||
n = do_read( fd, buffer, 1 );
|
||||
if( n == -1 ) {
|
||||
g10_log_error("read error on EGD: %s\n", strerror(errno));
|
||||
do_restart = 1;
|
||||
goto restart;
|
||||
}
|
||||
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
|
||||
fprintf( stderr,
|
||||
#else
|
||||
tty_printf(
|
||||
#endif
|
||||
_(
|
||||
"\n"
|
||||
"Not enough random bytes available. Please do some other work to give\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;
|
||||
_("Please wait, entropy is being gathered. Do some work if it would\n"
|
||||
"keep you from getting bored, because it will improve the quality\n"
|
||||
"of the entropy.\n") );
|
||||
}
|
||||
while( length ) {
|
||||
nbytes = length < 255? length : 255;
|
||||
|
||||
/* collect reply */
|
||||
do {
|
||||
n = read(fd, buffer, nbytes+2 );
|
||||
} while( n == -1 && errno == EINTR );
|
||||
/* process reply */
|
||||
if( n == -1 )
|
||||
buffer[0] = 2; /* blocking */
|
||||
buffer[1] = nbytes;
|
||||
if( do_write( fd, buffer, 2 ) == -1 )
|
||||
g10_log_fatal("can't write to the EGD: %s\n", strerror(errno) );
|
||||
n = do_read( fd, buffer, nbytes );
|
||||
if( n == -1 ) {
|
||||
g10_log_error("read error on EGD: %s\n", strerror(errno));
|
||||
else if( cmd == 2 && n != nbytes ) {
|
||||
g10_log_error("bad EGD reply: too short %d/%d\n", nbytes, n );
|
||||
do_restart = 1;
|
||||
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 );
|
||||
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) );
|
||||
|
||||
return 0; /* success */
|
||||
|
@ -28,11 +28,11 @@ dnl
|
||||
dnl Check for random module options
|
||||
dnl
|
||||
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_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] )
|
||||
|
||||
if test "$use_static_rnd" = no; then
|
||||
@ -169,7 +169,7 @@ case "${target}" in
|
||||
esac
|
||||
|
||||
AC_SUBST(MPI_OPT_FLAGS)
|
||||
AM_SYS_SYMBOL_UNDERSCORE
|
||||
GNUPG_SYS_SYMBOL_UNDERSCORE
|
||||
GNUPG_CHECK_PIC
|
||||
GNUPG_CHECK_RDYNAMIC
|
||||
if test "$NO_PIC" = yes; then
|
||||
|
45
doc/DETAILS
45
doc/DETAILS
@ -54,10 +54,9 @@ more arguments in future versions.
|
||||
BADSIG <long keyid> <username>
|
||||
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
|
||||
caused by a missing public key or an unsupported algorithm.
|
||||
No argument yet.
|
||||
|
||||
VALIDSIG <fingerprint in hex>
|
||||
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
|
||||
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_NEVER
|
||||
TRUST_MARGINAL
|
||||
@ -98,10 +104,16 @@ more arguments in future versions.
|
||||
SHM_GET
|
||||
SHM_GET_BOOL
|
||||
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
|
||||
@ -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)
|
||||
--------------
|
||||
Due to the fact that we use fingerprints to lookup keys, we can
|
||||
|
@ -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>
|
||||
|
||||
* keygen.c (do_create): Changed wording of the note (Hugh Daniel)
|
||||
|
@ -989,8 +989,10 @@ armor_filter( void *opaque, int control,
|
||||
iobuf_writestr(a, tail_strings[afx->what] );
|
||||
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"));
|
||||
write_status_text( STATUS_NODATA, "1" );
|
||||
}
|
||||
if( afx->truncated )
|
||||
log_info(_("invalid armor: line longer than %d characters\n"),
|
||||
MAX_LINELEN );
|
||||
|
20
g10/encode.c
20
g10/encode.c
@ -76,11 +76,13 @@ encode_simple( const char *filename, int mode )
|
||||
cipher_filter_context_t cfx;
|
||||
armor_filter_context_t afx;
|
||||
compress_filter_context_t zfx;
|
||||
text_filter_context_t tfx;
|
||||
int do_compress = opt.compress && !opt.rfc1991;
|
||||
|
||||
memset( &cfx, 0, sizeof cfx);
|
||||
memset( &afx, 0, sizeof afx);
|
||||
memset( &zfx, 0, sizeof zfx);
|
||||
memset( &tfx, 0, sizeof tfx);
|
||||
init_packet(&pkt);
|
||||
|
||||
/* prepare iobufs */
|
||||
@ -90,6 +92,9 @@ encode_simple( const char *filename, int mode )
|
||||
return G10ERR_OPEN_FILE;
|
||||
}
|
||||
|
||||
if( opt.textmode )
|
||||
iobuf_push_filter( inp, text_filter, &tfx );
|
||||
|
||||
cfx.dek = NULL;
|
||||
if( mode ) {
|
||||
s2k = m_alloc_clear( sizeof *s2k );
|
||||
@ -151,19 +156,19 @@ encode_simple( const char *filename, int mode )
|
||||
pt->namelen = 0;
|
||||
}
|
||||
/* 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
|
||||
* tracked this problem down. We use this temporary fix
|
||||
* (fixme: remove the && !mode )
|
||||
*/
|
||||
if( filename && !mode ) {
|
||||
if( filename && !opt.textmode && !mode ) {
|
||||
if( !(filesize = iobuf_get_filelength(inp)) )
|
||||
log_info(_("%s: WARNING: empty file\n"), filename );
|
||||
}
|
||||
else
|
||||
filesize = 0; /* stdin */
|
||||
pt->timestamp = make_timestamp();
|
||||
pt->mode = 'b';
|
||||
pt->mode = opt.textmode? 't' : 'b';
|
||||
pt->len = filesize;
|
||||
pt->buf = inp;
|
||||
pkt.pkttype = PKT_PLAINTEXT;
|
||||
@ -206,12 +211,14 @@ encode_crypt( const char *filename, STRLIST remusr )
|
||||
cipher_filter_context_t cfx;
|
||||
armor_filter_context_t afx;
|
||||
compress_filter_context_t zfx;
|
||||
text_filter_context_t tfx;
|
||||
PK_LIST pk_list;
|
||||
int do_compress = opt.compress && !opt.rfc1991;
|
||||
|
||||
memset( &cfx, 0, sizeof cfx);
|
||||
memset( &afx, 0, sizeof afx);
|
||||
memset( &zfx, 0, sizeof zfx);
|
||||
memset( &tfx, 0, sizeof tfx);
|
||||
init_packet(&pkt);
|
||||
|
||||
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 )
|
||||
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 )) )
|
||||
goto leave;
|
||||
|
||||
@ -270,14 +280,14 @@ encode_crypt( const char *filename, STRLIST remusr )
|
||||
pt = m_alloc( sizeof *pt - 1 );
|
||||
pt->namelen = 0;
|
||||
}
|
||||
if( filename ) {
|
||||
if( filename && !opt.textmode ) {
|
||||
if( !(filesize = iobuf_get_filelength(inp)) )
|
||||
log_info(_("%s: WARNING: empty file\n"), filename );
|
||||
}
|
||||
else
|
||||
filesize = 0; /* stdin */
|
||||
pt->timestamp = make_timestamp();
|
||||
pt->mode = 'b';
|
||||
pt->mode = opt.textmode ? 't' : 'b';
|
||||
pt->len = filesize;
|
||||
pt->new_ctb = !pt->len && !opt.rfc1991;
|
||||
pt->buf = inp;
|
||||
|
@ -824,6 +824,7 @@ main( int argc, char **argv )
|
||||
secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */
|
||||
|
||||
set_debug();
|
||||
g10_opt_homedir = opt.homedir;
|
||||
|
||||
/* must do this after dropping setuid, because string_to...
|
||||
* may try to load an module */
|
||||
|
29
g10/getkey.c
29
g10/getkey.c
@ -31,6 +31,7 @@
|
||||
#include "keydb.h"
|
||||
#include "options.h"
|
||||
#include "main.h"
|
||||
#include "trustdb.h"
|
||||
#include "i18n.h"
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
|
@ -144,6 +144,7 @@ int get_pubkey_byfprint( PKT_public_key *pk, const byte *fprint,
|
||||
size_t fprint_len );
|
||||
int get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint,
|
||||
size_t fprint_len );
|
||||
int get_keyblock_bylid( KBNODE *ret_keyblock, ulong lid );
|
||||
int seckey_available( u32 *keyid );
|
||||
int get_seckey_byname( PKT_secret_key *sk, const char *name, int unlock );
|
||||
int get_seckey_bynames( GETKEY_CTX *rx, PKT_secret_key *sk,
|
||||
|
@ -182,6 +182,14 @@ proc_pubkey_enc( CTX c, PACKET *pkt )
|
||||
* function to check it. */
|
||||
if( opt.verbose )
|
||||
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)
|
||||
|| enc->pubkey_algo == PUBKEY_ALGO_DSA
|
||||
|| is_RSA(enc->pubkey_algo) ) {
|
||||
@ -914,7 +922,11 @@ check_sig_and_print( CTX c, KBNODE node )
|
||||
g10_exit(1);
|
||||
}
|
||||
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) );
|
||||
}
|
||||
return rc;
|
||||
|
@ -133,6 +133,16 @@ passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode )
|
||||
: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 ) {
|
||||
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
|
||||
size_t n;
|
||||
@ -159,15 +169,6 @@ passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode )
|
||||
tty_printf("\n");
|
||||
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 ) {
|
||||
pw = next_pw;
|
||||
|
138
g10/pkclist.c
138
g10/pkclist.c
@ -107,8 +107,8 @@ show_paths( ulong lid, int only_first )
|
||||
/****************
|
||||
* Returns true if an ownertrust has changed.
|
||||
*/
|
||||
int
|
||||
edit_ownertrust( ulong lid, int mode )
|
||||
static int
|
||||
do_edit_ownertrust( ulong lid, int mode, unsigned *new_trust )
|
||||
{
|
||||
char *p;
|
||||
int rc;
|
||||
@ -117,6 +117,7 @@ edit_ownertrust( ulong lid, int mode )
|
||||
PKT_public_key *pk ;
|
||||
int changed=0;
|
||||
int quit=0;
|
||||
int show=0;
|
||||
|
||||
rc = keyid_from_lid( lid, keyid );
|
||||
if( rc ) {
|
||||
@ -177,14 +178,15 @@ edit_ownertrust( ulong lid, int mode )
|
||||
case '4': trust = TRUST_FULLY ; break;
|
||||
default: BUG();
|
||||
}
|
||||
if( !update_ownertrust( lid, trust ) )
|
||||
changed++;
|
||||
*new_trust = trust;
|
||||
changed = 1;
|
||||
break;
|
||||
}
|
||||
else if( *p == ans[0] || *p == ans[1] ) {
|
||||
tty_printf(_(
|
||||
"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 ) ) {
|
||||
break ; /* back to the menu */
|
||||
@ -197,73 +199,71 @@ edit_ownertrust( ulong lid, int mode )
|
||||
}
|
||||
m_free(p);
|
||||
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)
|
||||
* 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.
|
||||
*/
|
||||
static int
|
||||
add_ownertrust( PKT_public_key *pk, int *quit )
|
||||
add_ownertrust( PKT_public_key *pk, int *quit, unsigned *trustlevel )
|
||||
{
|
||||
int rc;
|
||||
void *context = NULL;
|
||||
ulong lid;
|
||||
unsigned otrust, validity;
|
||||
int any=0, changed=0, any_undefined=0;
|
||||
unsigned flags = 0;
|
||||
|
||||
*quit = 0;
|
||||
*trustlevel = 0;
|
||||
tty_printf(
|
||||
_("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"));
|
||||
|
||||
rc = query_trust_record( pk );
|
||||
if( rc ) {
|
||||
log_error("Ooops: not in trustdb\n");
|
||||
return -1;
|
||||
}
|
||||
rc = check_trust( pk, trustlevel, NULL, add_ownertrust_cb, &flags );
|
||||
|
||||
lid = pk->local_id;
|
||||
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 )
|
||||
if( !(flags & 1) )
|
||||
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") );
|
||||
else if( !changed )
|
||||
else if( !(flags & 4) )
|
||||
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 )
|
||||
{
|
||||
int rc;
|
||||
int did_add = 0;
|
||||
|
||||
retry:
|
||||
if( (trustlevel & TRUST_FLAG_REVOKED) ) {
|
||||
log_info(_("key %08lX: key has been revoked!\n"),
|
||||
(ulong)keyid_from_pk( pk, NULL) );
|
||||
@ -295,7 +297,7 @@ do_we_trust( PKT_public_key *pk, int trustlevel )
|
||||
g10_errstr(rc) );
|
||||
return 0; /* no */
|
||||
}
|
||||
rc = check_trust( pk, &trustlevel, NULL );
|
||||
rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
|
||||
if( rc )
|
||||
log_fatal("trust check after insert failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
@ -317,14 +319,10 @@ do_we_trust( PKT_public_key *pk, int trustlevel )
|
||||
else {
|
||||
int quit;
|
||||
|
||||
rc = add_ownertrust( pk, &quit );
|
||||
if( !rc && !quit ) {
|
||||
rc = check_trust( pk, &trustlevel, NULL );
|
||||
if( rc )
|
||||
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 );
|
||||
rc = add_ownertrust( pk, &quit, &trustlevel );
|
||||
if( !rc && !did_add && !quit ) {
|
||||
did_add = 1;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -353,10 +351,6 @@ do_we_trust( PKT_public_key *pk, int trustlevel )
|
||||
default: BUG();
|
||||
}
|
||||
|
||||
|
||||
/* Eventuell fragen falls der trustlevel nicht ausreichend ist */
|
||||
|
||||
|
||||
return 1; /* yes */
|
||||
}
|
||||
|
||||
@ -419,7 +413,7 @@ check_signatures_trust( PKT_signature *sig )
|
||||
{
|
||||
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
|
||||
int trustlevel;
|
||||
int dont_try = 0;
|
||||
int did_add = 0;
|
||||
int rc=0;
|
||||
|
||||
rc = get_pubkey( pk, sig->keyid );
|
||||
@ -429,13 +423,13 @@ check_signatures_trust( PKT_signature *sig )
|
||||
goto leave;
|
||||
}
|
||||
|
||||
retry:
|
||||
rc = check_trust( pk, &trustlevel, NULL );
|
||||
rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
|
||||
if( rc ) {
|
||||
log_error("check trust failed: %s\n", g10_errstr(rc));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
retry:
|
||||
if( (trustlevel & TRUST_FLAG_REVOKED) ) {
|
||||
write_status( STATUS_KEYREVOKED );
|
||||
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) );
|
||||
goto leave;
|
||||
}
|
||||
rc = check_trust( pk, &trustlevel, NULL );
|
||||
rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
|
||||
if( rc )
|
||||
log_fatal("trust check after insert failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
@ -464,7 +458,7 @@ check_signatures_trust( PKT_signature *sig )
|
||||
break;
|
||||
|
||||
case TRUST_UNDEFINED:
|
||||
if( dont_try || opt.batch || opt.answer_no ) {
|
||||
if( did_add || opt.batch || opt.answer_no ) {
|
||||
write_status( STATUS_TRUST_UNDEFINED );
|
||||
log_info(_(
|
||||
"WARNING: This key is not certified with a trusted signature!\n"));
|
||||
@ -474,9 +468,9 @@ check_signatures_trust( PKT_signature *sig )
|
||||
}
|
||||
else {
|
||||
int quit;
|
||||
rc = add_ownertrust( pk, &quit );
|
||||
rc = add_ownertrust( pk, &quit, &trustlevel );
|
||||
if( rc || quit ) {
|
||||
dont_try = 1;
|
||||
did_add = 1;
|
||||
rc = 0;
|
||||
}
|
||||
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)) ) {
|
||||
int trustlevel;
|
||||
|
||||
rc = check_trust( pk, &trustlevel, NULL );
|
||||
rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
|
||||
if( rc ) {
|
||||
log_error("error checking pk of `%s': %s\n",
|
||||
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 )) ) {
|
||||
int trustlevel;
|
||||
|
||||
rc = check_trust( pk, &trustlevel, NULL );
|
||||
rc = check_trust( pk, &trustlevel, NULL, NULL, NULL );
|
||||
if( rc ) {
|
||||
free_public_key( pk ); pk = NULL;
|
||||
log_error(_("%s: error checking key: %s\n"),
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "main.h"
|
||||
#include "options.h"
|
||||
#include "i18n.h"
|
||||
#include "status.h"
|
||||
|
||||
|
||||
static int
|
||||
@ -175,6 +176,14 @@ check_secret_key( PKT_secret_key *sk, int n )
|
||||
if( i )
|
||||
log_info(_("Invalid passphrase; please try again ...\n"));
|
||||
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() )
|
||||
break;
|
||||
}
|
||||
|
@ -99,6 +99,11 @@ write_status_text ( int no, const char *text)
|
||||
case STATUS_NEED_PASSPHRASE: s = "NEED_PASSPHRASE\n"; break;
|
||||
case STATUS_VALIDSIG : s = "VALIDSIG\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;
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,11 @@
|
||||
#define STATUS_NEED_PASSPHRASE 20
|
||||
#define STATUS_VALIDSIG 21
|
||||
#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 --*/
|
||||
void set_status_fd ( int fd );
|
||||
|
@ -633,12 +633,15 @@ tdbio_read_modify_stamp( int modify_down )
|
||||
}
|
||||
|
||||
void
|
||||
tdbio_write_modify_stamp( int down, int up )
|
||||
tdbio_write_modify_stamp( int up, int down )
|
||||
{
|
||||
TRUSTREC vr;
|
||||
int rc;
|
||||
ulong stamp;
|
||||
|
||||
if( !(up || down) )
|
||||
return;
|
||||
|
||||
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
|
||||
if( rc )
|
||||
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;
|
||||
|
||||
rc = tdbio_write_record( &vr );
|
||||
if( !rc )
|
||||
if( rc )
|
||||
log_fatal( _("%s: error writing version record: %s\n"),
|
||||
db_name, g10_errstr(rc) );
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected );
|
||||
int tdbio_write_record( TRUSTREC *rec );
|
||||
int tdbio_db_matches_options(void);
|
||||
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_sync(void);
|
||||
int tdbio_begin_transaction(void);
|
||||
|
363
g10/trustdb.c
363
g10/trustdb.c
@ -41,6 +41,7 @@
|
||||
#include "main.h"
|
||||
#include "i18n.h"
|
||||
#include "tdbio.h"
|
||||
#include "ttyio.h"
|
||||
|
||||
#if MAX_FINGERPRINT_LEN > 20
|
||||
#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 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 int do_check( TRUSTREC *drec, unsigned *trustlevel, const char *nhash);
|
||||
static void print_user_id( FILE *fp, const char *text, u32 *keyid );
|
||||
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 void upd_pref_record( TRUSTREC *urec, u32 *keyid, PKT_signature *sig );
|
||||
static void upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
|
||||
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
|
||||
* which are the ones from our secrings and the trusted keys */
|
||||
@ -375,6 +380,7 @@ keyid_from_lid( ulong lid, u32 *keyid )
|
||||
int rc;
|
||||
|
||||
init_trustdb();
|
||||
keyid[0] = keyid[1] = 0;
|
||||
rc = tdbio_read_record( lid, &rec, 0 );
|
||||
if( rc ) {
|
||||
log_error(_("error reading dir record for LID %lu: %s\n"),
|
||||
@ -622,20 +628,23 @@ init_trustdb()
|
||||
************* Print helpers ****************
|
||||
***********************************************/
|
||||
static void
|
||||
print_user_id( const char *text, u32 *keyid )
|
||||
print_user_id( FILE *fp, const char *text, u32 *keyid )
|
||||
{
|
||||
char *p;
|
||||
size_t n;
|
||||
|
||||
p = get_user_id( keyid, &n );
|
||||
if( *text ) {
|
||||
fputs( text, stdout);
|
||||
putchar(' ');
|
||||
if( fp ) {
|
||||
fprintf( fp, "%s \"", text );
|
||||
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);
|
||||
}
|
||||
|
||||
@ -699,35 +708,122 @@ print_path( int pathlen, TN ME .........., FILE *fp, ulong highlight )
|
||||
|
||||
|
||||
static void
|
||||
print_default_uid( ulong lid )
|
||||
print_default_uid( FILE *fp, ulong lid )
|
||||
{
|
||||
u32 keyid[2];
|
||||
|
||||
if( !keyid_from_lid( lid, keyid ) )
|
||||
print_user_id( "", keyid );
|
||||
print_user_id( fp, "", keyid );
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
for( kr=tree; kr; kr = kr->next ) {
|
||||
printf("%*s", indent*4, "" );
|
||||
printf("K%lu(ot=%d,val=%d) ", kr->lid,
|
||||
if( fp ) {
|
||||
fprintf( fp, "%*s", level*4, "" );
|
||||
fprintf( fp, "K%lu(ot=%d,val=%d) ", kr->lid,
|
||||
kr->n.k.ownertrust,
|
||||
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 ) {
|
||||
printf("%*s ", indent*4, "" );
|
||||
printf("U%lu(mc=%d,fc=%d,val=%d)\n", ur->lid,
|
||||
if( fp ) {
|
||||
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.fully_count,
|
||||
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.
|
||||
* Fixme: this list is not anymore anchored to another
|
||||
* record, so it should be put elsewehere in case of an error
|
||||
* FIXME: add mod_up/down handling
|
||||
*/
|
||||
static void
|
||||
process_hintlist( ulong hintlist, ulong hint_owner )
|
||||
@ -1184,7 +1281,8 @@ upd_key_record( KBNODE keyblock, KBNODE keynode, u32 *keyid,
|
||||
*/
|
||||
static void
|
||||
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;
|
||||
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 );
|
||||
if( !( urec.r.uid.uidflags & UIDF_VALID )
|
||||
|| ( urec.r.uid.uidflags & UIDF_REVOKED ) )
|
||||
; /*FIXME: mark as modified down */
|
||||
*mod_down=1;
|
||||
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 */
|
||||
@ -1362,11 +1460,11 @@ upd_uid_record( KBNODE keyblock, KBNODE uidnode, u32 *keyid,
|
||||
|
||||
if( (sig->sig_class&~3) == 0x10 ) { /* regular certification */
|
||||
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 */
|
||||
upd_cert_record( keyblock, node, keyid, drec, recno_list,
|
||||
recheck, &urec, uidhash, 1 );
|
||||
recheck, &urec, uidhash, 1, mod_up, mod_down );
|
||||
}
|
||||
} /* 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
|
||||
upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
|
||||
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
|
||||
* 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")
|
||||
: _("Good certificate") );
|
||||
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;
|
||||
*mod_down = 1;
|
||||
}
|
||||
else
|
||||
*mod_up = 1;
|
||||
}
|
||||
else if( rc == G10ERR_NO_PUBKEY ) {
|
||||
/* 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],
|
||||
_("public key not anymore available") );
|
||||
rec.r.sig.sig[i].flag = SIGF_NOPUBKEY;
|
||||
*mod_down = 1;
|
||||
if( revoked )
|
||||
rec.r.sig.sig[i].flag |= SIGF_REVOKED;
|
||||
}
|
||||
@ -1600,8 +1703,10 @@ upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
|
||||
: _("Invalid certificate"),
|
||||
g10_errstr(rc));
|
||||
rec.r.sig.sig[i].flag = SIGF_CHECKED;
|
||||
if( revoked )
|
||||
if( revoked ) {
|
||||
rec.r.sig.sig[i].flag |= SIGF_REVOKED;
|
||||
*mod_down = 1;
|
||||
}
|
||||
}
|
||||
rec.dirty = 1;
|
||||
}
|
||||
@ -1662,8 +1767,12 @@ upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
|
||||
: _("Good certificate") );
|
||||
newlid = pk_lid; /* this is the pk of the signature */
|
||||
newflag = SIGF_CHECKED | SIGF_VALID;
|
||||
if( revoked )
|
||||
if( revoked ) {
|
||||
newflag |= SIGF_REVOKED;
|
||||
*mod_down = 1;
|
||||
}
|
||||
else
|
||||
*mod_up = 1;
|
||||
}
|
||||
else if( rc == G10ERR_NO_PUBKEY ) {
|
||||
if( opt.verbose > 1 || DBG_TRUST )
|
||||
@ -1686,6 +1795,7 @@ upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
|
||||
newflag = SIGF_CHECKED;
|
||||
if( revoked )
|
||||
newflag |= SIGF_REVOKED;
|
||||
*mod_down = 1;
|
||||
}
|
||||
|
||||
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;
|
||||
u32 keyid[2]; /* keyid of primary key */
|
||||
ulong recno, lastrecno;
|
||||
int mod_up = 0;
|
||||
int mod_down = 0;
|
||||
RECNO_LIST recno_list = NULL; /* list of verified records */
|
||||
/* 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 ) {
|
||||
if( node->pkt->pkttype == PKT_USER_ID )
|
||||
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 */
|
||||
@ -1842,6 +1954,7 @@ update_trust_record( KBNODE keyblock, int recheck, int *modified )
|
||||
drec.r.dir.dirflags |= DIRF_CHECKED;
|
||||
drec.r.dir.valcheck = 0;
|
||||
write_record( &drec );
|
||||
tdbio_write_modify_stamp( mod_up, mod_down );
|
||||
rc = tdbio_end_transaction();
|
||||
}
|
||||
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.
|
||||
*/
|
||||
int
|
||||
insert_trust_record( PKT_public_key *pk )
|
||||
insert_trust_record( PKT_public_key *orig_pk )
|
||||
{
|
||||
TRUSTREC dirrec;
|
||||
TRUSTREC shadow;
|
||||
@ -1864,6 +1977,7 @@ insert_trust_record( PKT_public_key *pk )
|
||||
size_t fingerlen;
|
||||
int rc = 0;
|
||||
ulong hintlist = 0;
|
||||
PKT_public_key *pk;
|
||||
|
||||
|
||||
if( opt.dry_run )
|
||||
@ -1871,7 +1985,7 @@ insert_trust_record( PKT_public_key *pk )
|
||||
|
||||
init_trustdb();
|
||||
|
||||
fingerprint_from_pk( pk, fingerprint, &fingerlen );
|
||||
fingerprint_from_pk( orig_pk, fingerprint, &fingerlen );
|
||||
|
||||
/* fixme: assert that we do not have this record.
|
||||
* 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.)
|
||||
*/
|
||||
|
||||
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 */
|
||||
rc = get_keyblock_byfprint( &keyblock, fingerprint, fingerlen );
|
||||
if( rc ) { /* that should never happen */
|
||||
@ -1891,32 +2009,18 @@ insert_trust_record( PKT_public_key *pk )
|
||||
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 ) {
|
||||
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 );
|
||||
release_kbnode( keyblock );
|
||||
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
|
||||
* as the dir record. And: check all signatures which are listed
|
||||
* 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 */
|
||||
pk->local_id = dirrec.r.dir.lid;
|
||||
orig_pk->local_id = dirrec.r.dir.lid;
|
||||
for( node=keyblock; node; node = node->next ) {
|
||||
if( node->pkt->pkttype == PKT_PUBLIC_KEY
|
||||
|| 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 */
|
||||
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
|
||||
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;
|
||||
int max_validity = 0;
|
||||
@ -2112,7 +2266,9 @@ propagate_validity( TN node )
|
||||
/* this is one of our keys */
|
||||
assert( !node->list ); /* it should be a leaf */
|
||||
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 */
|
||||
@ -2120,11 +2276,39 @@ propagate_validity( TN node )
|
||||
assert( ur->is_uid );
|
||||
/* loop over all signators */
|
||||
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 ) {
|
||||
ur->n.u.fully_count = opt.completes_needed;
|
||||
}
|
||||
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 )
|
||||
ur->n.u.fully_count++;
|
||||
else if( kr->n.k.ownertrust == TRUST_MARGINAL )
|
||||
@ -2145,6 +2329,7 @@ propagate_validity( TN node )
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
int keytrust;
|
||||
int pv_result;
|
||||
|
||||
tree = build_cert_tree( drec->r.dir.lid, 0, opt.max_cert_depth, NULL );
|
||||
if( !tree )
|
||||
return TRUST_UNDEFINED;
|
||||
propagate_validity( tree );
|
||||
pv_result = propagate_validity( tree, tree, add_fnc, retflgs );
|
||||
if( namehash ) {
|
||||
/* find the matching user id.
|
||||
* 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;
|
||||
|
||||
/* update the cached validity values */
|
||||
if( keytrust >= TRUST_UNDEFINED
|
||||
if( !pv_result
|
||||
&& keytrust >= TRUST_UNDEFINED
|
||||
&& tdbio_db_matches_options()
|
||||
&& ( !drec->r.dir.valcheck || drec->r.dir.validity != keytrust ) ) {
|
||||
TN ur;
|
||||
@ -2213,7 +2401,8 @@ verify_key( int max_depth, TRUSTREC *drec, const char *namehash )
|
||||
* but nothing more is known.
|
||||
*/
|
||||
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 ) {
|
||||
log_error(_("Ooops, no keys\n"));
|
||||
@ -2224,22 +2413,39 @@ do_check( TRUSTREC *dr, unsigned *validity, const char *namehash )
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
|
||||
if( retflgs )
|
||||
*retflgs &= ~(16|32); /* reset the 2 special flags */
|
||||
|
||||
|
||||
if( namehash ) {
|
||||
/* 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
|
||||
> tdbio_read_modify_stamp( (dr->r.dir.validity < TRUST_FULLY) )
|
||||
&& dr->r.dir.validity )
|
||||
*validity = dr->r.dir.validity;
|
||||
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 )
|
||||
*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;
|
||||
}
|
||||
|
||||
@ -2256,6 +2462,9 @@ update_ownertrust( ulong lid, unsigned new_trust )
|
||||
|
||||
init_trustdb();
|
||||
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;
|
||||
write_record( &rec );
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
unsigned trustlevel = TRUST_UNKNOWN;
|
||||
@ -2562,7 +2772,7 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel, const byte *namehash )
|
||||
trustlevel = TRUST_EXPIRED;
|
||||
}
|
||||
else {
|
||||
rc = do_check( &rec, &trustlevel, namehash );
|
||||
rc = do_check( &rec, &trustlevel, namehash, add_fnc, retflgs );
|
||||
if( rc ) {
|
||||
log_error(_("key %08lX.%lu: trust check failed: %s\n"),
|
||||
(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;
|
||||
|
||||
init_trustdb();
|
||||
if( check_trust( pk, &trustlevel, namehash ) )
|
||||
if( check_trust( pk, &trustlevel, namehash, NULL, NULL ) )
|
||||
return '?';
|
||||
if( trustlevel & TRUST_FLAG_REVOKED )
|
||||
return 'r';
|
||||
@ -2656,12 +2866,15 @@ list_trust_path( const char *username )
|
||||
|
||||
tree = build_cert_tree( lid, 0, opt.max_cert_depth, NULL );
|
||||
if( tree )
|
||||
propagate_validity( tree );
|
||||
dump_tn_tree( 0, tree );
|
||||
printf("(alloced tns=%d max=%d)\n", alloced_tns, max_alloced_tns );
|
||||
propagate_validity( tree, tree, NULL, NULL );
|
||||
if( opt.with_colons )
|
||||
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 );
|
||||
printf("Ownertrust=%c Validity=%c\n", get_ownertrust_info( lid ),
|
||||
query_trust_info( pk, NULL ) );
|
||||
/*printf("Ownertrust=%c Validity=%c\n", get_ownertrust_info( lid ),
|
||||
query_trust_info( pk, NULL ) ); */
|
||||
|
||||
free_public_key( pk );
|
||||
|
||||
|
@ -47,7 +47,8 @@ void check_trustdb( const char *username );
|
||||
void update_trustdb( void );
|
||||
int setup_trustdb( int level, const char *dbname );
|
||||
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 enum_cert_paths( void **context, ulong *lid,
|
||||
unsigned *ownertrust, unsigned *validity );
|
||||
|
@ -88,6 +88,7 @@ typedef struct {
|
||||
|
||||
int g10c_debug_mode;
|
||||
int g10_opt_verbose;
|
||||
const char *g10_opt_homedir;
|
||||
|
||||
/*-- dynload.c --*/
|
||||
void register_cipher_extension( const char *mainpgm, const char *fname );
|
||||
|
Loading…
x
Reference in New Issue
Block a user