This commit is contained in:
Werner Koch 1998-07-14 17:10:28 +00:00
parent c5b6f97767
commit 0a76a4465b
41 changed files with 708 additions and 456 deletions

View File

@ -17,5 +17,8 @@ dist-hook:
|| cp -p $(srcdir)/$$dir/$$i $(distdir)/$$dir/$$i; \
done ; \
done
for file in po/cat-id-tbl.c po/gnupg.pot; do \
rm $(distdir)/$$file || true ; \
done

10
NEWS
View File

@ -1,3 +1,13 @@
Noteworthy changes in version 0.3.3
-----------------------------------
* Removed options --gen-prime and --gen-random.
* Signatures are now checked even if the output file could not
be created. Command "--verify" tries to find the detached data.
* gpg now disables core dumps.
Noteworthy changes in version 0.3.2
-----------------------------------
* Fixed some bugs when using --textmode (-seat)

134
README
View File

@ -1,9 +1,6 @@
-----BEGIN PGP SIGNED MESSAGE-----
GNUPG - The GNU Privacy Guard
-------------------------------
Version 0.3
GNUPG - The GNU Privacy Guard
-------------------------------
Version 0.3
As you can see from the version number, the program may have some
@ -51,7 +48,7 @@
is still available, but due to the larger size of such signatures it
is depreciated (Please note that the GNUPG implementation of ElGamal
signatures is *not* insecure). Symmetric algorithms are: Blowfish
and CAST5, Digest algorithms are MD5, RIPEMD160, SHA1 and TIGER/192.
and CAST5, Digest algorithms are MD5, RIPEMD160, SHA1 and TIGER/192.
@ -60,7 +57,7 @@
See the file INSTALL. Here is a quick summary:
1) "./configure"
1) "./configure"
2) "make"
@ -75,7 +72,7 @@
Key Generation
--------------
gpg --gen-key
gpg --gen-key
This asks some questions and then starts key generation. To create
good random numbers for prime number generation, it uses a /dev/random
@ -88,7 +85,7 @@
You should make a revocation certificate in case someone gets
knowledge of your secret key or you forgot your passphrase:
gpg --gen-revoke your_user_id
gpg --gen-revoke your_user_id
Run this command and store it away; output is always ASCII armored,
so that you can print it and (hopefully never) re-create it if
@ -97,18 +94,18 @@
If you decided to create a DSA key, you should add an ElGamal
for encryption:
gpg --add-key user_id_of_your_key
gpg --add-key user_id_of_your_key
and follow the displayed instructions (select "ElGamal using v4 packets").
You can sign a key with this command:
gpg --sign-key Donald
gpg --sign-key Donald
This let you sign the key of "Donald" with your default userid.
gpg --sign-key -u Karl -u Joe Donald
gpg --sign-key -u Karl -u Joe Donald
This let you sign the key of of "Donald" with the userids of "Karl"
and "Joe".
@ -117,7 +114,7 @@
whether you want to sign this key.
You may remove a signature at any time using the option "--edit-sig",
which asks for the sigs to remove. Self-signatures are not removable.
which asks for the sigs to remove. Self-signatures are not removable.
@ -125,16 +122,16 @@
Sign
----
gpg -s file
gpg -s file
This creates a file file.gpg which is compressed and has a signature
attached.
gpg -sa file
gpg -sa file
Same as above, but file.gpg is ascii armored.
gpg -s -o out file
gpg -s -o out file
Creates a signature of file, but writes the output to the file "out".
@ -142,12 +139,12 @@
Encrypt
-------
gpg -e -r heine file
gpg -e -r heine file
This encrypts files with the public key of "heine" and writes it
to "file.gpg"
echo "hallo" | gpg -ea -r heine | mail heine
echo "hallo" | gpg -ea -r heine | mail heine
Ditto, but encrypts "hallo\n" and mails it as ascii armored message.
@ -155,13 +152,13 @@
Sign and Encrypt
----------------
gpg -se -r heine file
gpg -se -r heine file
This encrypts files with the public key of "heine" and writes it
to "file.gpg" after signing it with the default user id.
gpg -se -r heine -u Suttner file
gpg -se -r heine -u Suttner file
Ditto, but sign the file with the user id "Suttner"
@ -170,17 +167,17 @@
------------------
To export your complete keyring(s) do this:
gpg --export
gpg --export
To export only some user ids do this:
gpg --export userids
gpg --export userids
Use "-a" or "--armor" to create ASCII armored output.
Importing keys is done with the option, you guessed it, "--import":
gpg --import [filenames]
gpg --import [filenames]
New keys are appended to the default keyring and already existing
keys are merged. Keys without a self-signature are ignored.
@ -192,40 +189,40 @@
* Only by the short keyid (prepend a zero if it begins with A..F):
"234567C4"
"0F34E556E"
"01347A56A"
"0xAB123456
"234567C4"
"0F34E556E"
"01347A56A"
"0xAB123456
* By a complete keyid:
"234AABBCC34567C4"
"0F323456784E56EAB"
"01AB3FED1347A5612"
"0x234AABBCC34567C4"
"234AABBCC34567C4"
"0F323456784E56EAB"
"01AB3FED1347A5612"
"0x234AABBCC34567C4"
* By a fingerprint:
"1234343434343434C434343434343434"
"123434343434343C3434343434343734349A3434"
"0E12343434343434343434EAB3484343434343434"
"1234343434343434C434343434343434"
"123434343434343C3434343434343734349A3434"
"0E12343434343434343434EAB3484343434343434"
The first one is MD5 the others are ripemd160 or sha1.
* By an exact string (not yet implemented):
"=Heinrich Heine <heinrichh@uni-duesseldorf.de>"
"=Heinrich Heine <heinrichh@uni-duesseldorf.de>"
* By an email address:
"<heinrichh@uni-duesseldorf.de>"
"<heinrichh@uni-duesseldorf.de>"
This can be used by a keyserver instead of a substring to
find this key faster.
* By the Local ID (from the trustdb):
"#34"
"#34"
This can be used by a MUA to specify an exact key after selecting
a key from GNUPG (by the use of a special option or an extra utility)
@ -233,8 +230,8 @@
* Or by the usual substring:
"Heine"
"*Heine"
"Heine"
"*Heine"
The '*' indicates substring search explicitly.
@ -264,21 +261,21 @@
Esoteric commands
-----------------
gpg --list-packets datafile
gpg --list-packets datafile
Use this to list the contents of a data file. If the file is encrypted
you are asked for the passphrase, so that GNUPG is able to look at the
inner structure of a encrypted packet.
gpgm --list-trustdb
gpgm --list-trustdb
List the contents of the trustdb in a human readable format
gpgm --list-trustdb <usernames>
gpgm --list-trustdb <usernames>
List the tree of certificates for the given usernames
gpgm --list-trust-path depth username
gpgm --list-trust-path depth username
List the possible trust paths for the given username, up to the specified
depth. If depth is negative, duplicate introducers are not listed,
@ -287,24 +284,10 @@
using a negative number). This option may create new entries in the
trustdb.
gpgm --print-mds filenames
gpgm --print-mds filenames
List all available message digest values for the fiven filenames
gpgm --gen-prime n
Generate and print a simple prime number of size n
gpgm --gen-prime n q
Generate a prime number suitable for ElGamal signatures of size n with
a q as largest prime factor of n-1.
gpgm --gen-prime n q 1
Ditto, but calculate a generator too.
For more options/commands see the file g10/OPTIONS, or use "gpg --help"
@ -314,17 +297,17 @@
can be used multiple times, all values are ORed; n maybe prefixed with
0x to use hex-values.
value used for
----- ----------------------------------------------
1 packet reading/writing
2 MPI details
4 ciphers and primes (may reveal sensitive data)
8 iobuf filter functions
16 iobuf stuff
32 memory allocation stuff
64 caching
128 show memory statistics at exit
256 trust verification stuff
value used for
----- ----------------------------------------------
1 packet reading/writing
2 MPI details
4 ciphers and primes (may reveal sensitive data)
8 iobuf filter functions
16 iobuf stuff
32 memory allocation stuff
64 caching
128 show memory statistics at exit
256 trust verification stuff
Other Notes
@ -342,14 +325,3 @@
post them to the mailing list <g10@net.lut.ac.uk> (this is a closed list,
please subscribe before posting).
-----BEGIN PGP SIGNATURE-----
Version: 2.6.3ia
Charset: noconv
iQB1AwUBNaIyMR0Z9MEMmFelAQGGFgMAm0RkKqH6DwIl3cu4ETQROprnwbl0sc21
05CQCsATs/0oQ8R2GhH1vXyHQnGw4Abg8IHqe+fADUA8cpf1ijfPzgeq+qhp7rqs
EenOw3xe8RrsrvovkCy91AtYl8zyVdC8
=IgnL
-----END PGP SIGNATURE-----

1
THANKS
View File

@ -23,6 +23,7 @@ Marco d'Itri md@linux.it
Mark Adler madler@alumni.caltech.edu
Martin Schulte schulte@thp.uni-koeln.de
Matthew Skala mskala@ansuz.sooke.bc.ca
Max Valianskiy maxcom@maxcom.ml.org
Nicolas Graner Nicolas.Graner@cri.u-psud.fr
Peter Gutmann pgut001@cs.auckland.ac.nz
Ralph Gillen gillen@theochem.uni-duesseldorf.de

26
TODO
View File

@ -1,25 +1,21 @@
* Change the internal represenation of keyid into a struct which
can also hold the localid and extend the localid to hold information
of the subkey number because two subkeys may have the same keyid.
* invalid packets (Marco)
* clearsig of zero length files does not work
* Change the inernal represenation of keyid into a struct which
can also hold the localid
* what about the CR,LF in cleartext singatures?
* add option --restore-ownertrust
* always put key signatures before the first subkey.
* Change the formatting of log_xxxx to GNU standards
("name:filename:line: text")
* add a way to delete subkeys (in edit-keys?)
* make preferences work
* rewrite --list-packets or put it into another tool.
* add field to PKT_user_id to hold the hash context
* add usage arguments to get_key_byname or return a PKC_LIST with
all keys and add a selection.
@ -28,14 +24,9 @@
* Burn the buffers used by fopen(), or use read(2). Does this
really make sense?
* enable a SIGSEGV handler while using zlib functions
* improve iobuf by reading more than one byte at once,
this shoud espceially done for the buffer in the chain.
Change the buffering to a mbuf like scheme? Need it for PSST anyway.
* add a way to distinguish between errors and eof in the underflow/flush
function of iobuf.
* Change the buffering to a mbuf like scheme? Need it for PSST anyway.
* add checking of armor trailers
* remove all "Fixmes"
@ -50,10 +41,5 @@
* add an option to re-create a public key from a secret key. Think about
a backup system of only the secret part of the secret key.
* add fingerprint/keyid hashing. We need a new field in PKC to
flag that we may have a cached signature for this (and use the address
of PKC to lookup the hash).
* replace getkey.c#enum_secret_keys

View File

@ -1 +1 @@
0.3.2
0.3.2b

View File

@ -22,8 +22,8 @@ dsa_keyrings="--keyring ./pubring.pkr --secret-keyring ./secring.skr"
plain_files="plain-1 plain-2 plain-3"
#data_files="data-500 data-9000 data-32000 data-80000"
data_files="data-500 data-9000"
data_files="data-500 data-9000 data-32000 data-80000"
#data_files="data-500 data-9000"
exp_files=""

View File

@ -1,3 +1,8 @@
Mon Jul 13 21:30:52 1998 Werner Koch (wk@isil.d.shuttle.de)
* random.c (read_pool): Simple alloc if secure_alloc is not set.
(get_random_bits): Ditto.
Thu Jul 9 13:01:14 1998 Werner Koch (wk@isil.d.shuttle.de)
* dynload.c (load_extension): Function now nbails out if

View File

@ -281,7 +281,6 @@ gen_prime( unsigned nbits, int secret, int randomlevel )
mods = m_alloc( no_of_small_prime_numbers * sizeof *mods );
/* make nbits fit into MPI implementation */
nlimbs = (nbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB;
assert( nlimbs );
val_2 = mpi_alloc( nlimbs );
mpi_set_ui(val_2, 2);
val_3 = mpi_alloc( nlimbs );

View File

@ -153,7 +153,7 @@ get_random_bits( size_t nbits, int level, int secure )
size_t nbytes = (nbits+7)/8;
MASK_LEVEL(level);
buf = secure? m_alloc_secure( nbytes ) : m_alloc( nbytes );
buf = secure && secure_alloc ? m_alloc_secure( nbytes ) : m_alloc( nbytes );
read_pool( buf, nbytes, level );
return buf;
}
@ -222,7 +222,7 @@ read_pool( byte *buffer, size_t length, int level )
needed = length - pool_balance;
if( needed > POOLSIZE )
BUG();
p = m_alloc_secure( needed );
p = secure_alloc ? m_alloc_secure( needed ) : m_alloc(needed);
read_random_source( p, needed, 2 ); /* read /dev/random */
add_randomness( p, needed, 3);
m_free(p);

View File

@ -182,7 +182,7 @@ fi
dnl Checks for library functions.
AC_FUNC_VPRINTF
AC_CHECK_FUNCS(strerror stpcpy strlwr tcgetattr rand strtoul mlock mmap)
AC_CHECK_FUNCS(memmove gettimeofday getrusage gethrtime)
AC_CHECK_FUNCS(memmove gettimeofday getrusage gethrtime setrlimit)
dnl check whether we have a random device

View File

@ -56,7 +56,7 @@ Record type 1:
--------------
Version information for this TrustDB. This is always the first
record of the DB and the only one with type 1.
1 byte value 1
1 byte value 2
3 bytes 'gpg' magic value
1 byte Version of the TrustDB
3 byte reserved
@ -81,42 +81,79 @@ Record type 2: (directory record)
These are static values which are never changed without user interaction.
1 byte value 2
1 byte reserved
8 bytes keyid (We keep it here to speed up searching by keyid)
1 u32 Local-Id. This is simply the record number of this record.
1 u32 primary public key (record number of it)
1 byte reserved
1 u32 LID . (This is simply the record number of this record.)
1 u32 List of key-records (the first one is the primary key)
1 u32 List of uid-records
1 u32 cache record
1 u32 sigrecord
1 byte No signatures flag (used to avoid duplicate building).
3 byte reserved
1 u32 userid record
6 byte reserved
1 byte ownertrust
1 byte sigflag
20 byte reserved
Record type 3:
Record type 3: (key record)
--------------
Informations about a primary public key.
These are static values which are never changed without user interaction.
(This is mainly used to lookup a trust record)
1 byte value 3
1 byte reserved
1 u32 owner This is used to bind all records for
a given certificate together. It is valid only in this TrustDB
and useful if we have duplicate keyids
It points back to the directory node.
1 byte pubkey algorithm
1 byte length of the fingerprint (in bytes)
1 byte reserved
1 u32 LID
1 u32 next - next key record
8 bytes reserved
1 byte pubkey algorithm
1 byte length of the fingerprint (in bytes)
20 bytes fingerprint of the public key
1 byte ownertrust if there is no trust defined for the userid:
3 byte reserved
(This is the value we use to identify a key)
Record type 4: (uid record)
--------------
Informations about a userid
We do not store the userid but the hash value of the userid because that
is sufficient.
1 byte value 4
1 byte reserved
1 u32 LID points to the directory record.
1 u32 next next userid
1 u32 pointer to preference record
1 u32 siglist list of valid signatures
2 byte reserved
20 bytes ripemd160 hash of the username.
Record type 4: (cache record)
Record type 5: (pref record)
--------------
Informations about preferences
1 byte value 5
1 byte reserved
1 u32 LID; points to the directory record (and not to the uid record!).
(or 0 for standard preference record)
1 u32 next
Record type 6 (sigrec)
-------------
Used to keep track of valid key signatures. Self-signatures are not
stored.
1 byte value 6
1 byte reserved
1 u32 LID points back to the dir record
1 u32 next next sigrec of this owner or 0 to indicate the
last sigrec.
6 times
1 u32 Local_id of signators dir record
1 byte reserved
Record type 9: (cache record)
--------------
Used to bind the trustDB to the concrete instance of keyblock in
a pubring. This is used to cache information.
1 byte value 4
1 byte value 9
1 byte reserved
1 u32 Local-Id.
8 bytes keyid of the primary key (needed?)
@ -141,23 +178,9 @@ Record type 4: (cache record)
4 = fully trusted
5 = ultimately trusted (have secret key too).
Record type 5 (sigrec)
-------------
Used to keep track of valid key signatures. Self-signatures are not
stored.
1 byte value 5
1 byte reserved
1 u32 For Local-Id (points back to the directory record)
1 u32 chain: next sigrec of this owner or 0 to indicate the
last sigrec.
6 times
1 u32 Local_id of signators pubkey record
1 byte reserved
Record Type 6 (hash table)
-------------
Record Type 10 (hash table)
--------------
Due to the fact that we use the keyid to lookup keys, we can
implement quick access by some simple hash methods, and avoid
the overhead of gdbm. A property of keyids is that they can be
@ -171,7 +194,7 @@ Record Type 6 (hash table)
big table. The hash value is simple the 1st, 2nd, ... byte of
the keyid (depending on the indirection level).
1 byte value 5
1 byte value 10
1 byte reserved
n u32 recnum; n depends on th record length:
n = (reclen-2)/4 which yields 9 for the current record length
@ -194,38 +217,19 @@ Record Type 6 (hash table)
if this is not the correct dir record, we look at the next
dir record which is linked by the link field.
Record type 7 (hash list)
-------------
Record type 11 (hash list)
--------------
see hash table for an explanation.
1 byte value 6
1 byte value 11
1 byte reserved
1 u32 chain next hash list record
1 u32 next next hash list record
n times n = (reclen-6)/5
1 byte hash
1 u32 recnum
For the current record length of 40, n is 6
Record type 8: (userid)
--------------
Informations about a userid
We do not store the userid but the hash value of the userid because that
is sufficient.
1 byte value 8
1 byte reserved
1 u32 owner; points to the directory record.
1 u32 next userid
1 byte subtype: 0 = a real user id
1 = not a real userid, but a "dummy" user of length 0
which is used to represent stuff that is directly
bound to the key.
20 bytes ripemd160 hash of the username.
1 u32 pointer to preference record
1 byte ownertrust
4 byte reserved
Packet Headers

View File

@ -1,6 +1,6 @@
## Process this file with automake to create Makefile.in
EXTRA_DIST = DETAILS rfcs gpg.1pod gpg.1
EXTRA_DIST = DETAILS rfcs gpg.1pod gpg.1 FAQ
man_MANS = gpg.1

View File

@ -55,7 +55,10 @@ B<--verify> [[I<sigfile>] {I<signed-files>}]
detached signature when not used in batch mode). If
only a sigfile is given, it may be a complete signature
or a detached signature, in which case the signed stuff
is expected from stdin. With more than 1 argument, the
is expected in a file without the I<.sig> or I<.asc>
extension (if such a file does not exist it is expected
at stdin - use B<-> as filename to force a read from
stdin). With more than 1 argument, the
first should be a detached signature and the remaining
files are the signed stuff.

View File

@ -1,3 +1,35 @@
Tue Jul 14 18:09:51 1998 Werner Koch (wk@isil.d.shuttle.de)
* keyid.c (fingerprint_from_pk): Add argument and changed all callers.
(fingerprint_from_sk): Ditto.
Tue Jul 14 10:10:03 1998 Werner Koch (wk@isil.d.shuttle.de)
* plaintext.c (handle_plaintext): Now returns create error if
the file could not be created or the user responded not to overwrite
the file.
* mainproc.c (proc_plaintext): Tries again if the file could not
be created to check the signature without output.
* misc.c (disable_core_dumps): New.
* g10.c (main): disable coredumps for gpg
* g10.c (MAINTAINER_OPTIONS): New to disable some options
Mon Jul 13 16:47:54 1998 Werner Koch (wk@isil.d.shuttle.de)
* plaintext.c (hash_datafiles): New arg for better support of
detached sigs. Changed all callers.
* mainproc.c (proc_signature_packets): Ditto.
* g10.c (main): New option "compress-sigs"
* sig.c (sign_file): detached signatures are not anymore compressed
unless the option --compress-sigs is used.
Thu Jul 9 19:54:54 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c: Fixes to allow zero length cleartext signatures
Thu Jul 9 14:52:47 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (build_list): Now drops setuid.

View File

@ -17,15 +17,7 @@
#-----------------------------------------------
#------------------- Commands ------------------
#-----------------------------------------------
# With some expections, these cannot be combined
gen-prime
# Generate a prime.
# With one argument: take it as the bitsize and make a simple prime of
# this size
# With two arguments: Generate a prime, usable for DL algorithms.
# With three arguments: same as above, but a third argument indicates
# that a generator should also be calculated.
# With some exceptions, these cannot be combined
print-md algo
# print the message digest of algorithm ALGO for stdin or all
@ -53,4 +45,7 @@ compress-keys
# algorithm with --compress-algo" - Default is to not compress keys, as
# this is better for interoperability.
compress-sigs
# Normally, compressing of signatures does not make sense; so this
# is disabled for detached signatures unless this option is used.

View File

@ -62,6 +62,7 @@ typedef enum {
fhdrSKIPHeader,
fhdrCLEARSIG,
fhdrREADClearsig,
fhdrNullClearsig,
fhdrEMPTYClearsig,
fhdrCHECKClearsig,
fhdrCHECKClearsig2,
@ -343,6 +344,8 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
*r_hashes |= hashes;
}
}
else if( clearsig && n > 15 && !memcmp(buf, "-----", 5 ) )
state = fhdrNullClearsig;
else
state = fhdrCHECKDashEscaped3;
}
@ -386,7 +389,10 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
buf[n++] = c;
if( n < buflen || c == '\n' ) {
buf[n] = 0;
state = fhdrCHECKDashEscaped3;
if( n > 15 && !memcmp(buf, "-----", 5 ) )
state = fhdrNullClearsig;
else
state = fhdrCHECKDashEscaped3;
}
else {
/* fixme: we should check whether this line continues
@ -396,6 +402,10 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
}
break;
case fhdrNullClearsig: /* zero length cleartext */
state = fhdrENDClearsig;
break;
case fhdrENDClearsig:
case fhdrCHECKBegin:
state = state == fhdrCHECKBegin ? fhdrINITSkip : fhdrERRORShow;
@ -587,10 +597,8 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
buf[1] = '\n';
n = 2;
}
}
*r_buflen = n;
*r_empty = empty;
return state;
@ -627,6 +635,7 @@ check_input( armor_filter_context_t *afx, IOBUF a )
rc = -1;
break;
case fhdrNullClearsig:
case fhdrCLEARSIG: /* start fake package mode (for clear signatures) */
afx->helplen = n;
afx->helpidx = 0;
@ -679,7 +688,8 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
rc = -1;
continue;
}
if( afx->helpidx < afx->helplen ) { /* flush the last buffer */
if( state != fhdrNullClearsig
&& afx->helpidx < afx->helplen ) { /* flush the last buffer */
n = afx->helplen;
for(nn=afx->helpidx; len < size && nn < n ; nn++ )
buf[len++] = afx->helpbuf[nn];
@ -693,7 +703,8 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
/* read a new one */
n = DIM(afx->helpbuf);
afx->helpidx = 0;
state = find_header( state, afx->helpbuf, &n, a, 0,
state = find_header( state, afx->helpbuf, &n, a,
state == fhdrNullClearsig? afx->helplen:0,
&emplines, &afx->hashes );
switch( state) {
case fhdrERROR:
@ -723,8 +734,10 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
buf[0] = (len-2) >> 8;
buf[1] = (len-2);
if( state == fhdrENDClearsig ) { /* write last (ending) length header */
buf[len++] = 0;
buf[len++] = 0;
if( buf[0] || buf[1] ) { /* write only if length of text is > 0 */
buf[len++] = 0;
buf[len++] = 0;
}
rc = 0;
}

View File

@ -25,6 +25,7 @@
#include <string.h>
#include <unistd.h>
/* #define MAINTAINER_OPTIONS */
#include "packet.h"
#include "iobuf.h"
@ -85,8 +86,10 @@ static ARGPARSE_OPTS opts[] = {
{ 547, "enarmor", 0, N_("En-Armor a file or stdin") },
{ 555, "print-md" , 0, N_("|algo [files]|print message digests")},
{ 516, "print-mds" , 0, N_("print all message digests")},
#ifdef MAINTAINER_OPTIONS
{ 513, "gen-prime" , 0, "@" },
{ 548, "gen-random" , 0, "@" },
#endif
#endif
{ 301, NULL, 0, N_("@\nOptions:\n ") },
@ -165,6 +168,7 @@ static ARGPARSE_OPTS opts[] = {
{ 508, "check-sig",0, "@" }, /* alias */
{ 553, "skip-verify",0, "@" },
{ 557, "compress-keys",0, "@"},
{ 566, "compress-sigs",0, "@"},
{ 559, "always-trust", 0, "@"},
{ 562, "emulate-checksum-bug", 0, "@"},
@ -413,6 +417,7 @@ main( int argc, char **argv )
*/
log_set_name("gpg");
secure_random_alloc(); /* put random number into secure memory */
disable_core_dumps();
init_signals();
#endif
i18n_init();
@ -529,15 +534,17 @@ main( int argc, char **argv )
#endif /* !IS_G10 */
#ifdef IS_G10MAINT
case 513: set_cmd( &cmd, aPrimegen); break;
case 514: set_cmd( &cmd, aTest); break;
#ifdef MAINTAINER_OPTIONS
case 513: set_cmd( &cmd, aPrimegen); break;
case 514: set_cmd( &cmd, aTest); break;
case 548: set_cmd( &cmd, aGenRandom); break;
#endif
case 516: set_cmd( &cmd, aPrintMDs); break;
case 531: set_cmd( &cmd, aListTrustDB); break;
case 533: set_cmd( &cmd, aListTrustPath); break;
case 540: break; /* dummy */
case 546: set_cmd( &cmd, aDeArmor); break;
case 547: set_cmd( &cmd, aEnArmor); break;
case 548: set_cmd( &cmd, aGenRandom); break;
case 555: set_cmd( &cmd, aPrintMD); break;
case 564: set_cmd( &cmd, aListOwnerTrust); break;
#endif /* IS_G10MAINT */
@ -596,6 +603,7 @@ main( int argc, char **argv )
case 562: opt.emulate_bugs |= 1; break;
case 563: set_cmd( &cmd, aExportSecret); break;
case 565: opt.do_not_export_rsa = 1; break;
case 566: opt.compress_sigs = 1; break;
default : errors++; pargs.err = configfp? 1:2; break;
}
}
@ -725,16 +733,16 @@ main( int argc, char **argv )
if( argc > 1 )
wrong_args(_("--store [filename]"));
if( (rc = encode_store(fname)) )
log_error("%s: store failed: %s\n",
print_fname_stdin(fname), g10_errstr(rc) );
log_error_f( print_fname_stdin(fname),
"store failed: %s\n", g10_errstr(rc) );
break;
#ifdef IS_G10
case aSym: /* encrypt the given file only with the symmetric cipher */
if( argc > 1 )
wrong_args(_("--symmetric [filename]"));
if( (rc = encode_symmetric(fname)) )
log_error("%s: symmetric encryption failed: %s\n",
print_fname_stdin(fname), g10_errstr(rc) );
log_error_f(print_fname_stdin(fname),
"symmetric encryption failed: %s\n",g10_errstr(rc) );
break;
case aEncr: /* encrypt the given file */
@ -933,6 +941,7 @@ main( int argc, char **argv )
break;
#ifdef MAINTAINER_OPTIONS
case aPrimegen:
if( argc == 1 ) {
mpi_print( stdout, generate_public_prime( atoi(argv[0]) ), 1);
@ -960,7 +969,9 @@ main( int argc, char **argv )
else
usage(1);
break;
#endif /* MAINTAINER OPTIONS */
#ifdef MAINTAINER_OPTIONS
case aGenRandom:
if( argc < 1 || argc > 2 )
wrong_args("--gen-random level [hex]");
@ -977,6 +988,7 @@ main( int argc, char **argv )
}
}
break;
#endif /* MAINTAINER OPTIONS */
case aPrintMD:
if( argc < 1)
@ -1007,7 +1019,9 @@ main( int argc, char **argv )
}
break;
#ifdef MAINTAINER_OPTIONS
case aTest: do_test( argc? atoi(*argv): 1 ); break;
#endif /* MAINTAINER OPTIONS */
case aListTrustDB:
if( !argc )
@ -1085,7 +1099,7 @@ do_not_use_RSA()
if( !did_rsa_note ) {
did_rsa_note = 1;
log_info(_("RSA keys are depreciated; please consider "
log_info(_("RSA keys are deprecated; please consider "
"creating a new key and use this key in the future\n"));
}
}
@ -1194,10 +1208,12 @@ print_mds( const char *fname, int algo )
#ifdef MAINTAINER_OPTIONS
static void
do_test(int times)
{
m_check(NULL);
}
#endif /* MAINTAINER OPTIONS */
#endif /* IS_G10MAINT */

View File

@ -758,7 +758,7 @@ lookup( PKT_public_key *pk, int mode, u32 *keyid,
else if( mode == 16 || mode == 20 ) {
size_t an;
byte *afp = fingerprint_from_pk(
k->pkt->pkt.public_key, &an );
k->pkt->pkt.public_key, NULL, &an );
if( DBG_CACHE ) {
u32 aki[2];
@ -897,7 +897,7 @@ lookup_sk( PKT_secret_key *sk, int mode, u32 *keyid, const char *name )
else if( mode == 16 || mode == 20 ) {
size_t an;
byte *afp = fingerprint_from_sk(
k->pkt->pkt.secret_key, &an );
k->pkt->pkt.secret_key, NULL, &an );
if( an == mode && !memcmp( afp, name, an)
&& ( !sk->pubkey_algo
|| sk->pubkey_algo

View File

@ -25,6 +25,7 @@
#include "packet.h"
#include "cipher.h"
#define MAX_FINGERPRINT_LEN 20
/****************
@ -80,11 +81,12 @@ struct pubkey_find_info {
u32 keyid[2];
unsigned nbits;
byte pubkey_algo;
byte fingerprint[20];
byte fingerprint[MAX_FINGERPRINT_LEN];
char userid[1];
};
/*-- pkclist.c --*/
int check_signatures_trust( PKT_signature *sig );
void release_pk_list( PK_LIST pk_list );
@ -128,8 +130,8 @@ unsigned nbits_from_sk( PKT_secret_key *sk );
const char *datestr_from_pk( PKT_public_key *pk );
const char *datestr_from_sk( PKT_secret_key *sk );
const char *datestr_from_sig( PKT_signature *sig );
byte *fingerprint_from_sk( PKT_secret_key *sk, size_t *ret_len );
byte *fingerprint_from_pk( PKT_public_key *pk, size_t *ret_len );
byte *fingerprint_from_sk( PKT_secret_key *sk, byte *buf. size_t *ret_len );
byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
/*-- kbnode.c --*/
KBNODE new_kbnode( PACKET *pkt );

View File

@ -45,7 +45,7 @@ show_fingerprint( PKT_public_key *pk )
byte *array, *p;
size_t i, n;
p = array = fingerprint_from_pk( pk, &n );
p = array = fingerprint_from_pk( pk, NULL, &n );
tty_printf(" Fingerprint:");
if( n == 20 ) {
for(i=0; i < n ; i++, i++, p += 2 ) {
@ -292,7 +292,7 @@ sign_key( const char *username, STRLIST locusr )
if( !opt.batch ) {
/* ask whether we really should do anything */
answer = tty_get(
_("To you want to remove some of the invalid sigs? "));
_("Do you want to remove some of the invalid signatures? "));
tty_kill_prompt();
if( answer_is_yes(answer) )
remove_keysigs( keyblock, pk_keyid, 0 );

View File

@ -442,9 +442,9 @@ ask_keysize( int algo )
else if( nbits < 768 )
tty_printf(_("keysize too small; 768 is smallest value allowed.\n"));
else if( nbits > 2048 ) {
tty_printf(_("Keysizes larger than 2048 are not suggested, because "
tty_printf(_("Keysizes larger than 2048 are not suggested because "
"computations take REALLY long!\n"));
answer = tty_get(_("Are you sure, that you want this keysize? "));
answer = tty_get(_("Are you sure that you want this keysize? "));
tty_kill_prompt();
if( answer_is_yes(answer) ) {
m_free(answer);
@ -685,7 +685,7 @@ ask_passphrase( STRING2KEY **ret_s2k )
tty_printf(_(
"You don't want a passphrase - this is probably a *bad* idea!\n"
"I will do it anyway. You can change your passphrase at any time,\n"
"using this program with the option \"--change-passphrase\"\n\n"));
"using this program with the option \"--change-passphrase\".\n\n"));
break;
}
else

View File

@ -262,13 +262,13 @@ datestr_from_sig( PKT_signature *sig )
/**************** .
* Return a byte array with the fingerprint for the given PK/SK
* The length of the array is returned in ret_len. Caller must free
* the array.
* the array or provide array as buffer of length MAX_FINGERPRINT_LEN
*/
byte *
fingerprint_from_pk( PKT_public_key *pk, size_t *ret_len )
fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len )
{
byte *p, *buf, *array;
byte *p, *buf;
const char *dp;
size_t len;
unsigned n;
@ -287,7 +287,8 @@ fingerprint_from_pk( PKT_public_key *pk, size_t *ret_len )
m_free(buf);
}
md_final(md);
array = m_alloc( 16 );
if( !array )
array = m_alloc( 16 );
len = 16;
memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 );
md_close(md);
@ -297,7 +298,9 @@ fingerprint_from_pk( PKT_public_key *pk, size_t *ret_len )
md = do_fingerprint_md(pk);
dp = md_read( md, 0 );
len = md_digest_length( md_get_algo( md ) );
array = m_alloc( len );
assert( len <= MAX_FINGERPRINT_LEN );
if( !array )
array = m_alloc( len );
memcpy(array, dp, len );
md_close(md);
}
@ -307,9 +310,9 @@ fingerprint_from_pk( PKT_public_key *pk, size_t *ret_len )
}
byte *
fingerprint_from_sk( PKT_secret_key *sk, size_t *ret_len )
fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len )
{
byte *p, *buf, *array;
byte *p, *buf;
const char *dp;
size_t len;
unsigned n;
@ -328,7 +331,8 @@ fingerprint_from_sk( PKT_secret_key *sk, size_t *ret_len )
m_free(buf);
}
md_final(md);
array = m_alloc( 16 );
if( !array )
array = m_alloc( 16 );
len = 16;
memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 );
md_close(md);
@ -338,7 +342,9 @@ fingerprint_from_sk( PKT_secret_key *sk, size_t *ret_len )
md = do_fingerprint_md_sk(sk);
dp = md_read( md, 0 );
len = md_digest_length( md_get_algo( md ) );
array = m_alloc( len );
assert( len <= MAX_FINGERPRINT_LEN );
if( !array )
array = m_alloc( len );
memcpy(array, dp, len );
md_close(md);
}

View File

@ -339,8 +339,8 @@ fingerprint( PKT_public_key *pk, PKT_secret_key *sk )
byte *array, *p;
size_t i, n;
p = array = pk? fingerprint_from_pk( pk, &n )
: fingerprint_from_sk( sk, &n );
p = array = pk? fingerprint_from_pk( pk, NULL, &n )
: fingerprint_from_sk( sk, NULL, &n );
if( opt.with_colons ) {
printf("fpr:::::::::");
for(i=0; i < n ; i++, p++ )

View File

@ -47,6 +47,7 @@ void do_not_use_RSA(void);
/*-- misc.c --*/
void trap_unaligned(void);
void disable_core_dumps(void);
u16 checksum_u16( unsigned n );
u16 checksum( byte *p, unsigned n );
u16 checksum_mpi( MPI a );
@ -119,7 +120,8 @@ int verify_signatures( int nfiles, char **files );
int decrypt_message( const char *filename );
/*-- plaintext.c --*/
int hash_datafiles( MD_HANDLE md, STRLIST files, int textmode );
int hash_datafiles( MD_HANDLE md, STRLIST files, const char *sigfilename,
int textmode );
/*-- signal.c --*/
void init_signals(void);

View File

@ -51,6 +51,7 @@ typedef struct {
int sigs_only; /* process only signatures and reject all other stuff */
int encrypt_only; /* process only encrytion messages */
STRLIST signed_data;
const char *sigfilename;
DEK *dek;
int last_was_session_key;
KBNODE list; /* the current list of packets */
@ -262,7 +263,7 @@ proc_plaintext( CTX c, PACKET *pkt )
clearsig = 1;
}
}
if( !any ) { /* no onepass sig packet: enable all algos */
if( !any ) { /* no onepass sig packet: enable all standard algos */
md_enable( c->mfx.md, DIGEST_ALGO_RMD160 );
md_enable( c->mfx.md, DIGEST_ALGO_SHA1 );
md_enable( c->mfx.md, DIGEST_ALGO_MD5 );
@ -273,13 +274,13 @@ proc_plaintext( CTX c, PACKET *pkt )
m_check( c->mfx.md->list );
}
rc = handle_plaintext( pt, &c->mfx, c->sigs_only, clearsig );
if( rc == G10ERR_CREATE_FILE && !c->sigs_only) {
/* can't write output but we hash it anyway to
* check the signature */
rc = handle_plaintext( pt, &c->mfx, 1, clearsig );
}
if( rc )
log_error( "handle plaintext failed: %s\n", g10_errstr(rc));
if( c->mfx.md ) {
m_check(c->mfx.md);
if( c->mfx.md->list )
m_check( c->mfx.md->list );
}
free_packet(pkt);
c->last_was_session_key = 0;
}
@ -288,7 +289,8 @@ proc_plaintext( CTX c, PACKET *pkt )
static int
proc_compressed_cb( IOBUF a, void *info )
{
return proc_signature_packets( a, ((CTX)info)->signed_data );
return proc_signature_packets( a, ((CTX)info)->signed_data,
((CTX)info)->sigfilename );
}
static int
@ -405,8 +407,8 @@ print_fingerprint( PKT_public_key *pk, PKT_secret_key *sk )
byte *array, *p;
size_t i, n;
p = array = sk? fingerprint_from_sk( sk, &n )
: fingerprint_from_pk( pk, &n );
p = array = sk? fingerprint_from_sk( sk, NULL, &n )
: fingerprint_from_pk( pk, NULL, &n );
if( opt.with_colons ) {
printf("fpr:::::::::");
for(i=0; i < n ; i++, p++ )
@ -665,12 +667,13 @@ proc_packets( IOBUF a )
}
int
proc_signature_packets( IOBUF a, STRLIST signedfiles )
proc_signature_packets( IOBUF a, STRLIST signedfiles, const char *sigfilename )
{
CTX c = m_alloc_clear( sizeof *c );
int rc;
c->sigs_only = 1;
c->signed_data = signedfiles;
c->sigfilename = sigfilename;
rc = do_proc_packets( c, a );
m_free( c );
return rc;
@ -881,7 +884,7 @@ proc_tree( CTX c, KBNODE node )
}
/* ask for file and hash it */
if( c->sigs_only )
rc = hash_datafiles( c->mfx.md, c->signed_data,
rc = hash_datafiles( c->mfx.md, c->signed_data, c->sigfilename,
n1->pkt->pkt.onepass_sig->sig_class == 0x01 );
else
rc = ask_for_detached_datafile( &c->mfx,
@ -902,7 +905,7 @@ proc_tree( CTX c, KBNODE node )
free_md_filter_context( &c->mfx );
c->mfx.md = md_open(sig->digest_algo, 0);
if( c->sigs_only )
rc = hash_datafiles( c->mfx.md, c->signed_data,
rc = hash_datafiles( c->mfx.md, c->signed_data, c->sigfilename,
sig->sig_class == 0x01 );
else
rc = ask_for_detached_datafile( &c->mfx,

View File

@ -22,10 +22,15 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#if defined(__linux__) && defined(__alpha__)
#include <asm/sysinfo.h>
#include <asm/unistd.h>
#endif
#ifdef HAVE_SETRLIMIT
#include <sys/time.h>
#include <sys/resource.h>
#endif
#include "util.h"
#include "main.h"
#include "options.h"
@ -70,6 +75,23 @@ trap_unaligned(void)
#endif
void
disable_core_dumps()
{
#ifdef HAVE_SETRLIMIT
struct rlimit limit;
limit.rlim_cur = 0;
limit.rlim_max = 0;
if( setrlimit( RLIMIT_CORE, &limit ) )
log_fatal("can't disable core dumps: %s\n", strerror(errno) );
#else
log_info("WARNING: Program may create a core file!\n");
#endif
}
u16
checksum_u16( unsigned n )
{

View File

@ -142,6 +142,8 @@ open_sigfile( const char *iname )
buf = m_strdup(iname);
buf[len-4] = 0 ;
a = iobuf_open( buf );
if( opt.verbose )
log_info("assuming signed data in '%s'\n", buf );
m_free(buf);
}
}

View File

@ -47,6 +47,7 @@ struct {
const char *homedir;
int skip_verify;
int compress_keys;
int compress_sigs;
int always_trust;
int rfc1991;
unsigned emulate_bugs; /* bug emulation flags */

View File

@ -222,7 +222,7 @@ typedef enum {
/*-- mainproc.c --*/
int proc_packets( IOBUF a );
int proc_signature_packets( IOBUF a, STRLIST signedfiles );
int proc_signature_packets( IOBUF a, STRLIST signedfiles, const char *sigfile );
int proc_encryption_packets( IOBUF a );
int list_packets( IOBUF a );

View File

@ -63,7 +63,7 @@ query_ownertrust( ulong lid )
return 0;
}
tty_printf(_("No ownertrust defined for %lu:\n"
tty_printf(_("No owner trust defined for %lu:\n"
"%4u%c/%08lX %s \""), lid,
nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ),
(ulong)keyid[1], datestr_from_pk( pk ) );
@ -143,7 +143,7 @@ _("Could not find a valid trust path to the key. Let's see whether we\n"
while( !(rc=enum_trust_web( &context, &lid )) ) {
rc = get_ownertrust( lid, &trust );
if( rc )
log_fatal("Ooops: couldn't get ownertrust for %lu\n", lid);
log_fatal("Ooops: couldn't get owner trust for %lu\n", lid);
if( trust == TRUST_UNDEFINED || trust == TRUST_EXPIRED ||
trust == TRUST_UNKNOWN ) {
if( query_ownertrust( lid ) )
@ -155,7 +155,7 @@ _("Could not find a valid trust path to the key. Let's see whether we\n"
enum_trust_web( &context, NULL ); /* close */
if( !any )
tty_printf(_("No ownertrust values changed.\n\n") );
tty_printf(_("No owner trust values changed.\n\n") );
return rc? rc : any? 0:-1;
}
@ -366,7 +366,7 @@ check_signatures_trust( PKT_signature *sig )
case TRUST_MARGINAL:
write_status( STATUS_TRUST_MARGINAL );
log_info(_(
"WARNING: This key is not certified with enough trusted signatures!\n"
"WARNING: This key is not certified with sufficiently trusted signatures!\n"
));
log_info(_(
" It is not certain that the signature belongs to the owner.\n"

View File

@ -109,14 +109,17 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
/* no filename or "-" given; write to stdout */
fp = stdout;
}
else if( overwrite_filep( fname ) )
else if( (rc=overwrite_filep( fname )) ) {
if( rc == -1 )
rc = G10ERR_CREATE_FILE;
goto leave;
}
if( fp || nooutput )
;
else if( !(fp = fopen(fname,"wb")) ) {
log_error("Error creating '%s': %s\n", fname, strerror(errno) );
rc = G10ERR_WRITE_FILE;
rc = G10ERR_CREATE_FILE;
goto leave;
}
@ -245,20 +248,43 @@ ask_for_detached_datafile( md_filter_context_t *mfx, const char *inname )
}
static void
do_hash( MD_HANDLE md, IOBUF fp, int textmode )
{
text_filter_context_t tfx;
int c;
if( textmode ) {
memset( &tfx, 0, sizeof tfx);
iobuf_push_filter( fp, text_filter, &tfx );
}
while( (c = iobuf_get(fp)) != -1 )
md_putc(md, c );
}
/****************
* Hash the given files and append the hash to hash context md.
* If FILES is NULL, hash stdin.
*/
int
hash_datafiles( MD_HANDLE md, STRLIST files, int textmode )
hash_datafiles( MD_HANDLE md, STRLIST files,
const char *sigfilename, int textmode )
{
IOBUF fp;
STRLIST sl=NULL;
text_filter_context_t tfx;
int c;
if( !files )
if( !files ) {
/* check whether we can opne the signed material */
fp = open_sigfile( sigfilename );
if( fp ) {
do_hash( md, fp, textmode );
iobuf_close(fp);
return 0;
}
/* no we can't (no sigfile) - read signed stuff from stdin */
add_to_strlist( &sl, "-");
}
else
sl = files;
@ -271,12 +297,7 @@ hash_datafiles( MD_HANDLE md, STRLIST files, int textmode )
free_strlist(sl);
return G10ERR_OPEN_FILE;
}
if( textmode ) {
memset( &tfx, 0, sizeof tfx);
iobuf_push_filter( fp, text_filter, &tfx );
}
while( (c = iobuf_get(fp)) != -1 )
md_putc(md, c );
do_hash( md, fp, textmode );
iobuf_close(fp);
}

View File

@ -86,6 +86,7 @@ encode_session_key( DEK *dek, unsigned nbits )
frame[n++] = 2;
i = nframe - 6 - dek->keylen;
assert( i > 0 );
/* FIXME: replace the loop by a call to get_random_bits() */
for( ; i ; i-- ) {
while( !(c = get_random_byte(1)) )
;

View File

@ -226,7 +226,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
iobuf_push_filter( out, encrypt_filter, &efx );
}
if( opt.compress && !outfile ) {
if( opt.compress && !outfile && ( !detached || opt.compress_sigs) ) {
if( old_style )
zfx.algo = 1;
iobuf_push_filter( out, compress_filter, &zfx );

View File

@ -147,7 +147,7 @@ create_db( const char *fname )
fp =fopen( fname, "w" );
if( !fp )
log_fatal_f( fname, _("can't create %s: %s\n"), strerror(errno) );
fwrite_8( fp, 1 );
fwrite_8( fp, 2 );
fwrite_8( fp, 'g' );
fwrite_8( fp, 'p' );
fwrite_8( fp, 'g' );
@ -195,55 +195,67 @@ tdbio_dump_record( ulong rnum, TRUSTREC *rec, FILE *fp )
case RECTYPE_VER: fprintf(fp, "version\n");
break;
case RECTYPE_DIR:
fprintf(fp, "dir keyid=%08lX, key=%lu, ctl=%lu, sig=%lu",
(ulong)rec->r.dir.keyid[1],
rec->r.dir.keyrec, rec->r.dir.ctlrec, rec->r.dir.sigrec );
if( rec->r.dir.no_sigs == 1 )
fprintf(fp, "dir %lu, keys=%lu, uids=%lu, cach=%lu, ot=%02x",
rec->r.dir.lid,
rec->r.dir.keylist,
rec->r.dir.uidlist,
rec->r.dir.cacherec,
rec->r.dir.ownertrust );
if( rec->r.dir.sigflag == 1 )
fputs(", (none)", fp );
else if( rec->r.dir.no_sigs == 2 )
else if( rec->r.dir.sigflag == 2 )
fputs(", (invalid)", fp );
else if( rec->r.dir.no_sigs == 3 )
else if( rec->r.dir.sigflag == 3 )
fputs(", (revoked)", fp );
else if( rec->r.dir.no_sigs )
else if( rec->r.dir.sigflag )
fputs(", (??)", fp );
putc('\n', fp);
break;
case RECTYPE_KEY: fprintf(fp,
"key %08lX, own=%lu, ownertrust=%02x, fl=%d\n",
(ulong)rec->r.key.keyid[1],
rec->r.key.owner, rec->r.key.ownertrust,
case RECTYPE_KEY:
fprintf(fp, "key %lu, next=%lu, algo=%d, flen=%d\n",
rec->r.key.lid,
rec->r.key.next,
rec->r.key.pubkey_algo,
rec->r.key.fingerprint_len );
break;
case RECTYPE_UID:
if( !rec->r.uid.subtype )
fprintf(fp,
"uid %02x%02x, owner=%lu, chain=%lu, pref=%lu, otr=%02x\n",
rec->r.uid.namehash[18], rec->r.uid.namehash[19],
rec->r.uid.owner, rec->r.uid.chain, (ulong)rec->r.uid.prefrec,
rec->r.uid.ownertrust );
else
fprintf(fp,
"uid subtype%d, owner=%lu, chain=%lu\n",
rec->r.uid.subtype, rec->r.uid.owner, rec->r.uid.chain);
fprintf(fp, "uid %lu, next=%lu, pref=%lu, sig=%lu, hash=%02X%02X\n",
rec->r.uid.lid,
rec->r.uid.next,
rec->r.uid.prefrec,
rec->r.uid.siglist,
rec->r.uid.namehash[18], rec->r.uid.namehash[19]);
break;
case RECTYPE_CTL: fprintf(fp, "ctl\n");
case RECTYPE_PREF:
fprintf(fp, "pref %lu, next=%lu\n",
rec->r.uid.lid,
rec->r.uid.next);
break;
case RECTYPE_SIG:
fprintf(fp, "sigrec, owner=%lu, chain=%lu\n",
rec->r.sig.owner, rec->r.sig.chain );
fprintf(fp, "sig %lu, next=%lu\n",
rec->r.sig.lid, rec->r.sig.next );
for(i=any=0; i < SIGS_PER_RECORD; i++ ) {
if( rec->r.sig.sig[i].local_id ) {
if( rec->r.sig.sig[i].lid ) {
if( !any ) {
putc('\t', fp);
any++;
}
fprintf(fp, " %lu:%02x", rec->r.sig.sig[i].local_id,
rec->r.sig.sig[i].flag );
fprintf(fp, " %lu:%02x", rec->r.sig.sig[i].lid,
rec->r.sig.sig[i].flag );
}
}
if( any )
putc('\n', fp);
break;
case RECTYPE_CACH:
fprintf(fp, "cach\n");
break;
case RECTYPE_HTBL:
fprintf(fp, "htbl\n");
break;
case RECTYPE_HTBL:
fprintf(fp, "hlst\n");
break;
default:
fprintf(fp, "%d (unknown)\n", rec->rectype );
break;
@ -287,8 +299,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
case 0: /* unused record */
break;
case RECTYPE_VER: /* version record */
/* g10 was the original name */
if( memcmp(buf+1, "gpg", 3 ) && memcmp(buf+1, "g10", 3 ) ) {
if( memcmp(buf+1, "gpg", 3 ) ) {
log_error_f( db_name, _("not a trustdb file\n") );
rc = G10ERR_TRUSTDB;
}
@ -306,51 +317,60 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
(ulong)recnum );
rc = G10ERR_TRUSTDB;
}
if( rec->r.ver.version != 1 ) {
if( rec->r.ver.version != 2 ) {
log_error_f( db_name, "invalid file version %d\n",
rec->r.ver.version );
rc = G10ERR_TRUSTDB;
}
break;
case RECTYPE_DIR: /*directory record */
rec->r.dir.local_id = buftoulong(p); p += 4;
rec->r.dir.keyid[0] = buftou32(p); p += 4;
rec->r.dir.keyid[1] = buftou32(p); p += 4;
rec->r.dir.keyrec = buftoulong(p); p += 4;
rec->r.dir.ctlrec = buftoulong(p); p += 4;
rec->r.dir.sigrec = buftoulong(p); p += 4;
rec->r.dir.no_sigs = *p++;
if( rec->r.dir.local_id != recnum ) {
log_error_f( db_name, "dir local_id != recnum (%lu,%lu)\n",
(ulong)rec->r.dir.local_id,
(ulong)recnum );
rec->r.dir.lid = buftoulong(p); p += 4;
rec->r.dir.keylist = buftoulong(p); p += 4;
rec->r.dir.uidlist = buftoulong(p); p += 4;
rec->r.dir.cacherec = buftoulong(p); p += 4;
rec->r.dir.ownertrust = *p++;
rec->r.dir.sigflag = *p++;
if( rec->r.dir.lid != recnum ) {
log_error_f( db_name, "dir LID != recnum (%lu,%lu)\n",
rec->r.dir.lid, (ulong)recnum );
rc = G10ERR_TRUSTDB;
}
break;
case RECTYPE_KEY: /* public key record */
rec->r.key.owner = buftoulong(p); p += 4;
rec->r.dir.keyid[0] = buftou32(p); p += 4;
rec->r.dir.keyid[1] = buftou32(p); p += 4;
rec->r.key.lid = buftoulong(p); p += 4;
rec->r.key.next = buftoulong(p); p += 4;
p += 8;
rec->r.key.pubkey_algo = *p++;
rec->r.key.fingerprint_len = *p++;
if( rec->r.key.fingerprint_len < 1 || rec->r.key.fingerprint_len > 20 )
rec->r.key.fingerprint_len = 20;
memcpy( rec->r.key.fingerprint, p, 20); p += 20;
rec->r.key.ownertrust = *p++;
memcpy( rec->r.key.fingerprint, p, 20);
break;
case RECTYPE_CTL: /* control record */
rec->r.ctl.owner = buftoulong(p); p += 4;
memcpy(rec->r.ctl.blockhash, p, 20); p += 20;
rec->r.ctl.trustlevel = *p++;
case RECTYPE_UID: /* user id record */
rec->r.uid.lid = buftoulong(p); p += 4;
rec->r.uid.next = buftoulong(p); p += 4;
rec->r.uid.prefrec = buftoulong(p); p += 4;
rec->r.uid.siglist = buftoulong(p); p += 4;
p += 2;
memcpy( rec->r.uid.namehash, p, 20);
break;
case RECTYPE_PREF: /* preference record */
rec->r.pref.lid = buftoulong(p); p += 4;
rec->r.pref.next = buftoulong(p); p += 4;
break;
case RECTYPE_SIG:
rec->r.sig.owner = buftoulong(p); p += 4;
rec->r.sig.chain = buftoulong(p); p += 4;
rec->r.sig.lid = buftoulong(p); p += 4;
rec->r.sig.next = buftoulong(p); p += 4;
for(i=0; i < SIGS_PER_RECORD; i++ ) {
rec->r.sig.sig[i].local_id = buftoulong(p); p += 4;
rec->r.sig.sig[i].lid = buftoulong(p); p += 4;
rec->r.sig.sig[i].flag = *p++;
}
break;
case RECTYPE_CACH: /* cache record (FIXME)*/
rec->r.cache.lid = buftoulong(p); p += 4;
memcpy(rec->r.cache.blockhash, p, 20); p += 20;
rec->r.cache.trustlevel = *p++;
break;
default:
log_error_f( db_name, "invalid record type %d at recnum %lu\n",
rec->rectype, (ulong)recnum );
@ -385,40 +405,53 @@ tdbio_write_record( ulong recnum, TRUSTREC *rec )
break;
case RECTYPE_DIR: /*directory record */
ulongtobuf(p, rec->r.dir.local_id); p += 4;
u32tobuf(p, rec->r.key.keyid[0]); p += 4;
u32tobuf(p, rec->r.key.keyid[1]); p += 4;
ulongtobuf(p, rec->r.dir.keyrec); p += 4;
ulongtobuf(p, rec->r.dir.ctlrec); p += 4;
ulongtobuf(p, rec->r.dir.sigrec); p += 4;
*p++ = rec->r.dir.no_sigs;
assert( rec->r.dir.local_id == recnum );
ulongtobuf(p, rec->r.dir.lid); p += 4;
ulongtobuf(p, rec->r.dir.keylist); p += 4;
ulongtobuf(p, rec->r.dir.uidlist); p += 4;
ulongtobuf(p, rec->r.dir.cacherec); p += 4;
*p++ = rec->r.dir.ownertrust;
*p++ = rec->r.dir.sigflag;
assert( rec->r.dir.lid == recnum );
break;
case RECTYPE_KEY:
ulongtobuf(p, rec->r.key.owner); p += 4;
u32tobuf(p, rec->r.key.keyid[0]); p += 4;
u32tobuf(p, rec->r.key.keyid[1]); p += 4;
ulongtobuf(p, rec->r.key.lid); p += 4;
ulongtobuf(p, rec->r.key.next); p += 4;
p += 8;
*p++ = rec->r.key.pubkey_algo;
*p++ = rec->r.key.fingerprint_len;
memcpy( p, rec->r.key.fingerprint, 20); p += 20;
*p++ = rec->r.key.ownertrust;
break;
case RECTYPE_CTL: /* control record */
ulongtobuf(p, rec->r.ctl.owner); p += 4;
memcpy(p, rec->r.ctl.blockhash, 20); p += 20;
*p++ = rec->r.ctl.trustlevel;
case RECTYPE_UID: /* user id record */
ulongtobuf(p, rec->r.uid.lid); p += 4;
ulongtobuf(p, rec->r.uid.next); p += 4;
ulongtobuf(p, rec->r.uid.prefrec); p += 4;
ulongtobuf(p, rec->r.uid.siglist); p += 4;
p += 2;
memcpy( p, rec->r.uid.namehash, 20 ); p += 20;
break;
case RECTYPE_PREF:
ulongtobuf(p, rec->r.pref.lid); p += 4;
ulongtobuf(p, rec->r.pref.next); p += 4;
break;
case RECTYPE_SIG:
ulongtobuf(p, rec->r.sig.owner); p += 4;
ulongtobuf(p, rec->r.sig.chain); p += 4;
ulongtobuf(p, rec->r.sig.lid); p += 4;
ulongtobuf(p, rec->r.sig.next); p += 4;
for(i=0; i < SIGS_PER_RECORD; i++ ) {
ulongtobuf(p, rec->r.sig.sig[i].local_id); p += 4;
ulongtobuf(p, rec->r.sig.sig[i].lid); p += 4;
*p++ = rec->r.sig.sig[i].flag;
}
break;
case RECTYPE_CACH: /* FIXME*/
ulongtobuf(p, rec->r.cache.lid); p += 4;
memcpy(p, rec->r.cache.blockhash, 20); p += 20;
*p++ = rec->r.cache.trustlevel;
break;
default:
BUG();
}
@ -475,7 +508,7 @@ tdbio_new_recnum()
* Note: To increase performance, we could use a index search here.
*/
int
tdbio_search_record( PKT_public_key *pk, TRUSTREC *rec )
tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec )
{
ulong recnum;
u32 keyid[2];
@ -484,30 +517,26 @@ tdbio_search_record( PKT_public_key *pk, TRUSTREC *rec )
int rc;
keyid_from_pk( pk, keyid );
fingerprint = fingerprint_from_pk( pk, &fingerlen );
fingerprint = fingerprint_from_pk( pk, NULL, &fingerlen );
assert( fingerlen == 20 || fingerlen == 16 );
for(recnum=1; !(rc=tdbio_read_record( recnum, rec, 0)); recnum++ ) {
if( rec->rectype != RECTYPE_DIR )
if( rec->rectype != RECTYPE_KEY )
continue;
if( rec->r.dir.keyid[0] == keyid[0]
&& rec->r.dir.keyid[1] == keyid[1]){
TRUSTREC keyrec;
if( tdbio_read_record( rec->r.dir.keyrec, &keyrec, RECTYPE_KEY ) ) {
log_error("%lu: ooops: invalid key record\n", recnum );
if( rec->r.key.pubkey_algo == pk->pubkey_algo
&& !memcmp(rec->r.key.fingerprint, fingerprint, fingerlen) ) {
/* found: read the dir record for this key */
rc = tdbio_read_record( rec->r.key.lid, rec, RECTYPE_DIR);
if( rc )
break;
}
if( keyrec.r.key.pubkey_algo == pk->pubkey_algo
&& !memcmp(keyrec.r.key.fingerprint, fingerprint, fingerlen) ){
if( pk->local_id && pk->local_id != recnum )
log_error_f(db_name,
"found record, but local_id from memory does "
"not match recnum (%lu,%lu)\n",
(ulong)pk->local_id, (ulong)recnum );
pk->local_id = recnum;
return 0;
}
if( pk->local_id && pk->local_id != recnum )
log_error_f(db_name,
"found record, but LID from memory does "
"not match recnum (%lu,%lu)\n",
pk->local_id, recnum );
pk->local_id = recnum;
return 0;
}
}
if( rc != -1 )
@ -516,3 +545,22 @@ tdbio_search_record( PKT_public_key *pk, TRUSTREC *rec )
}
int
tdbio_update_sigflag( ulong lid, int sigflag )
{
TRUSTREC rec;
if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) {
log_error("update_sigflag: read failed\n");
return G10ERR_TRUSTDB;
}
rec.r.dir.sigflag = sigflag;
if( tdbio_write_record( lid, &rec ) ) {
log_error("update_sigflag: write failed\n");
return G10ERR_TRUSTDB;
}
return 0;
}

View File

@ -32,15 +32,17 @@
#define RECTYPE_VER 1
#define RECTYPE_DIR 2
#define RECTYPE_KEY 3
#define RECTYPE_CTL 4
#define RECTYPE_SIG 5
#define RECTYPE_HTBL 6
#define RECTYPE_HLST 7
#define RECTYPE_UID 8
#define RECTYPE_UID 4
#define RECTYPE_PREF 5
#define RECTYPE_SIG 6
#define RECTYPE_CACH 9
#define RECTYPE_HTBL 10
#define RECTYPE_HLST 11
struct trust_record {
int rectype;
struct trust_record *next;
union {
struct { /* version record: */
byte version; /* should be 1 */
@ -53,49 +55,50 @@ struct trust_record {
byte max_cert_depth;
} ver;
struct { /* directory record */
ulong local_id;
u32 keyid[2];
ulong keyrec; /* recno of primary public key record */
ulong ctlrec; /* recno of control record */
ulong sigrec; /* recno of first signature record (osolete) */
ulong uidrec; /* recno of first user-id record */
ulong link; /* to next dir record */
byte no_sigs; /* does not have sigature and checked */
ulong lid;
ulong keylist; /* List of keys (the first is the primary key)*/
ulong uidlist; /* list of uid records */
ulong cacherec; /* the cache record */
byte ownertrust;
byte sigflag;
} dir;
struct { /* primary public key record */
ulong owner;
u32 keyid[2];
ulong lid;
ulong next; /* next key */
byte pubkey_algo;
byte fingerprint_len;
byte fingerprint[20];
byte ownertrust;
} key;
struct { /* user id reord */
ulong owner; /* point back to the directory record */
ulong chain; /* points to next user id record */
byte subtype; /* must be 0 */
byte namehash[20]; /* ripemd hash of the username */
byte ownertrust;
u32 prefrec; /* recno of reference record */
ulong lid; /* point back to the directory record */
ulong next; /* points to next user id record */
ulong prefrec; /* recno of reference record */
ulong siglist; /* list of valid signatures (w/o self-sig)*/
byte namehash[20]; /* ripemd hash of the username */
} uid;
struct { /* control record */
ulong owner;
byte blockhash[20];
byte trustlevel; /* calculated trustlevel */
} ctl;
struct { /* preference reord */
ulong lid; /* point back to the directory record */
/* or 0 for a glocal pref record */
ulong next; /* points to next pref record */
} pref;
struct { /* signature record */
ulong owner; /* local_id of record owner (pubkey record) */
ulong chain; /* offset of next record or NULL for last one */
ulong lid;
ulong next; /* recnno of next record or NULL for last one */
struct {
ulong local_id; /* of pubkey record of signator (0=unused) */
byte flag; /* reserved */
ulong lid; /* of pubkey record of signator (0=unused) */
byte flag; /* reserved */
} sig[SIGS_PER_RECORD];
} sig;
struct { /* cache record */
ulong lid;
byte blockhash[20];
byte trustlevel; /* calculated trustlevel */
} cache;
struct {
ulong item[ITEMS_PER_HTBL_RECORD];
} htbl;
struct {
ulong chain;
ulong next;
struct {
byte hash;
ulong rnum;
@ -126,7 +129,8 @@ void tdbio_dump_record( ulong rnum, TRUSTREC *rec, FILE *fp );
int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected );
int tdbio_write_record( ulong recnum, TRUSTREC *rec );
ulong tdbio_new_recnum(void);
int tdbio_search_record( PKT_public_key *pk, TRUSTREC *rec );
int tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec );
int tdbio_update_sigflag( ulong lid, int sigflag );
#define buftoulong( p ) ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \

View File

@ -42,6 +42,10 @@
#include "tdbio.h"
#if MAX_FINGERPRINT_LEN > 20
#error Must change structure of trustdb
#endif
typedef struct local_id_info *LOCAL_ID_INFO;
struct local_id_info {
LOCAL_ID_INFO next;
@ -85,11 +89,10 @@ static int do_list_path( TRUST_INFO *stack, int depth, int max_depth,
LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist );
static int list_sigs( ulong pubkey_id );
static int build_sigrecs( ulong pubkeyid );
static int build_sigrecs( ulong local_id );
static int propagate_trust( TRUST_SEG_LIST tslist );
static int do_check( ulong pubkeyid, TRUSTREC *drec, unsigned *trustlevel );
static int do_check( TRUSTREC *drec, unsigned *trustlevel );
static int update_no_sigs( ulong lid, int no_sigs );
/* a table used to keep track of ultimately trusted keys
* which are the ones from our secrings */
@ -186,12 +189,11 @@ set_signature_packets_local_id( PKT_signature *sig )
if( rc)
goto leave;
if( !pk->local_id ) {
rc = tdbio_search_record( pk, &rec );
rc = tdbio_search_dir_record( pk, &rec );
if( rc == -1 )
rc = insert_trust_record( pk );
if( rc )
goto leave;
/* fixme: we should propagate the local_id to all copies of the PK */
}
sig->local_id = pk->local_id;
@ -666,35 +668,36 @@ check_sigs( KBNODE keyblock, int *selfsig_okay, int *revoked )
* to the trustdb
*/
static int
build_sigrecs( ulong pubkeyid )
build_sigrecs( ulong lid )
{
TRUSTREC rec, krec, rec2;
KBNODE keyblock = NULL;
KBNODE node;
KBNODE keyblock = NULL;
KBNODE node;
int rc=0;
int i, selfsig, revoked;
ulong rnum, rnum2;
ulong first_sigrec = 0;
if( DBG_TRUST )
log_debug("trustdb: build_sigrecs for pubkey %lu\n", (ulong)pubkeyid );
log_debug("trustdb: build_sigrecs for LID %lu\n", lid );
/* get the keyblock */
if( (rc=tdbio_read_record( pubkeyid, &rec, RECTYPE_DIR )) ) {
log_error(_("%lu: build_sigrecs: can't read dir record\n"), pubkeyid );
if( (rc=tdbio_read_record( lid, &rec, RECTYPE_DIR )) ) {
log_error( "build_sigrecs: can't read dir record %lu\n"), lid );
goto leave;
}
if( (rc=tdbio_read_record( rec.r.dir.keyrec, &krec, RECTYPE_KEY )) ) {
log_error(_("%lu: build_sigrecs: can't read key record\n"), pubkeyid);
if( (rc=tdbio_read_record( rec.r.dir.keylist, &krec, RECTYPE_KEY )) ) {
log_error("build_sigrecs: can't read primary key record %lu\n"), lid);
goto leave;
}
rc = get_keyblock_byfprint( &keyblock, krec.r.key.fingerprint,
krec.r.key.fingerprint_len );
if( rc ) {
log_error(_("build_sigrecs: get_keyblock_byfprint failed: %s\n"),
g10_errstr(rc) );
log_error( "build_sigrecs: keyblock for %lu not found: %s\n",
lid, g10_errstr(rc) );
goto leave;
}
/* check all key signatures */
rc = check_sigs( keyblock, &selfsig, &revoked );
if( rc ) {
@ -703,19 +706,18 @@ build_sigrecs( ulong pubkeyid )
}
if( !selfsig ) {
log_error(_("build_sigrecs: self-signature missing\n") );
update_no_sigs( pubkeyid, 2 );
tdbio_update_sigflag( lid, 2 );
rc = G10ERR_BAD_CERT;
goto leave;
}
if( revoked ) {
log_info(_("build_sigrecs: key has been revoked\n") );
update_no_sigs( pubkeyid, 3 );
tdbio_update_sigflag( lid, 3 );
}
else
update_no_sigs( pubkeyid, 0 ); /* assume we have sigs */
tdbio_update_sigflag( lid, 0 ); /* assume we have sigs */
/* valid key signatures are now marked; we can now build the
* sigrecs */
/* valid key signatures are now marked; we can now build the sigrecs */
memset( &rec, 0, sizeof rec );
rec.rectype = RECTYPE_SIG;
i = 0;
@ -740,8 +742,8 @@ build_sigrecs( ulong pubkeyid )
/* write the record */
rnum = tdbio_new_recnum();
if( rnum2 ) { /* write the stored record */
rec2.r.sig.owner = pubkeyid;
rec2.r.sig.chain = rnum; /* the next record number */
rec2.r.sig.lid = lid;
rec2.r.sig.next = rnum; /* the next record number */
rc = tdbio_write_record( rnum2, &rec2 );
if( rc ) {
log_error(_("build_sigrecs: write_record failed\n") );
@ -756,7 +758,7 @@ build_sigrecs( ulong pubkeyid )
rec.rectype = RECTYPE_SIG;
i = 0;
}
rec.r.sig.sig[i].local_id = node->pkt->pkt.signature->local_id;
rec.r.sig.sig[i].lid = node->pkt->pkt.signature->local_id;
rec.r.sig.sig[i].flag = 0;
i++;
}
@ -765,8 +767,8 @@ build_sigrecs( ulong pubkeyid )
/* write the record */
rnum = tdbio_new_recnum();
if( rnum2 ) { /* write the stored record */
rec2.r.sig.owner = pubkeyid;
rec2.r.sig.chain = rnum;
rec2.r.sig.lid = lid;
rec2.r.sig.next = rnum;
rc = tdbio_write_record( rnum2, &rec2 );
if( rc ) {
log_error(_("build_sigrecs: write_record failed\n") );
@ -776,8 +778,8 @@ build_sigrecs( ulong pubkeyid )
first_sigrec = rnum2;
}
if( i ) { /* write the pending record */
rec.r.sig.owner = pubkeyid;
rec.r.sig.chain = 0;
rec.r.sig.lid = lid;
rec.r.sig.next = 0;
rc = tdbio_write_record( rnum, &rec );
if( rc ) {
log_error(_("build_sigrecs: write_record failed\n") );
@ -787,8 +789,7 @@ build_sigrecs( ulong pubkeyid )
first_sigrec = rnum;
}
}
if( first_sigrec ) {
/* update the dir record */
if( first_sigrec ) { /* update the uid records */
if( (rc =tdbio_read_record( pubkeyid, &rec, RECTYPE_DIR )) ) {
log_error(_("update_dir_record: read failed\n"));
goto leave;
@ -800,7 +801,7 @@ build_sigrecs( ulong pubkeyid )
}
}
else
update_no_sigs( pubkeyid, revoked? 3:1 ); /* no signatures */
tdbio_update_sigflag( lid, revoked? 3:1 ); /* no signatures */
leave:
release_kbnode( keyblock );
@ -900,12 +901,24 @@ propagate_trust( TRUST_SEG_LIST tslist )
}
/****************
* we have the pubkey record but nothing more is known.
* (function may re-read dr)
* check whether we already build signature records
* Return: true if we have.
*/
static int
do_check( ulong pubkeyid, TRUSTREC *dr, unsigned *trustlevel )
do_we_have_sigs( TRUSTREC *dr )
{
}
/****************
* we have the pubkey record and all needed informations are in the trustdb
* but nothing more is known.
* (this function may re-read the dir record dr)
*/
static int
do_check( TRUSTREC *dr, unsigned *trustlevel )
{
int i, rc=0;
TRUST_SEG_LIST tsl, tsl2, tslist;
@ -919,16 +932,27 @@ do_check( ulong pubkeyid, TRUSTREC *dr, unsigned *trustlevel )
*trustlevel = TRUST_UNDEFINED;
if( !dr->r.dir.keylist ) {
log_error("Ooops, no keys\n");
return G10ERR_TRUSTDB
}
if( !dr->r.dir.uidlist ) {
log_error("Ooops, no user ids\n");
return G10ERR_TRUSTDB
}
/* verify the cache */
/* do we have sigrecs */
if( !dr->r.dir.sigrec && !dr->r.dir.no_sigs) {
/* no sigrecs, so build them */
rc = build_sigrecs( pubkeyid );
if( !do_we_have_sigs( dr ) ) { /* no sigrecs, so build them */
rc = build_sigrecs( dr->lid );
if( !rc ) /* and read again */
rc = tdbio_read_record( pubkeyid, dr, RECTYPE_DIR );
rc = tdbio_read_record( dr->lid, dr, RECTYPE_DIR );
}
!!!!WORK!!!!
if( dr->r.dir.no_sigs == 3 )
tflags |= TRUST_FLAG_REVOKED;
@ -1199,9 +1223,7 @@ list_trust_path( int max_depth, const char *username )
* yes: return trustlevel from cache
* no: make a cache record and all the other stuff
* not found:
* Return with a trustlevel, saying that we do not have
* a trust record for it. The caller may use insert_trust_record()
* and then call this function here again.
* try to insert the pubkey into the trustdb and check again
*
* Problems: How do we get the complete keyblock to check that the
* cache record is actually valid? Think we need a clever
@ -1225,17 +1247,17 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel )
/* get the pubkey record */
if( pk->local_id ) {
if( tdbio_read_record( pk->local_id, &rec, RECTYPE_DIR ) ) {
log_error(_("check_trust: read dir record failed\n"));
log_error("check_trust: read dir record failed\n");
return G10ERR_TRUSTDB;
}
}
else { /* no local_id: scan the trustdb */
if( (rc=tdbio_search_record( pk, &rec )) && rc != -1 ) {
log_error(_("check_trust: search_record failed: %s\n"),
if( (rc=tdbio_search_dir_record( pk, &rec )) && rc != -1 ) {
log_error("check_trust: search dir record failed: %s\n",
g10_errstr(rc));
return rc;
}
else if( rc == -1 ) {
else if( rc == -1 ) { /* not found - insert */
rc = insert_trust_record( pk );
if( rc ) {
log_error(_("key %08lX: insert trust record failed: %s\n"),
@ -1263,7 +1285,7 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel )
trustlevel = TRUST_EXPIRED;
}
else {
rc = do_check( pk->local_id, &rec, &trustlevel );
rc = do_check( &rec, &trustlevel );
if( rc ) {
log_error(_("key %08lX.%lu: trust check failed: %s\n"),
keyid[1], pk->local_id, g10_errstr(rc));
@ -1424,24 +1446,119 @@ query_trust_record( PKT_public_key *pk )
* This function fails if this record already exists.
*/
int
insert_trust_record( PKT_public_key *pk )
insert_trust_record( PKT_public_key *orig_pk )
{
TRUSTREC rec;
TRUSTREC dirrec, *rec;
TRUSTREC **keylist_tail, *keylist;
TRUSTREC **uidlist_tail, *uidlist;
KBNODE keyblock = NULL;
KBNODE node;
u32 keyid[2];
ulong knum, dnum;
byte *fingerprint;
size_t fingerlen;
int rc = 0;
if( pk->local_id )
if( orig_pk->local_id )
log_bug("pk->local_id=%lu\n", (ulong)pk->local_id );
keyid_from_pk( pk, keyid );
fingerprint = fingerprint_from_pk( pk, &fingerlen );
fingerprint = fingerprint_from_pk( orig_pk, &fingerlen );
/* fixme: assert that we do not have this record.
* we can do this by searching for the primary keyid
*/
/* get the keyblock which has the key */
rc = get_keyblock_byfprint( &keyblock, fingerprint, fingerlen );
if( rc ) { /* that should never happen */
log_error( "insert_trust_record: keyblock not found: %s\n",
g10_errstr(rc) );
return rc;
}
/* prepare dir record */
memset( &dirrec, 0, sizeof dirrec );
dirrec.rectype = RECTYPE_DIR;
dirrec.r.dir.lid = tdbio_new_recnum();
keylist = NULL;
keylist_tail = &dirrec.r.dir.keylist;
uidlist = NULL;
uidlist_tail = &dirrec.r.dir.uidlist;
/* loop over the keyblock */
for( node=keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
PKT_public_key *pk = node->pkt->pkt.public_key;
if( keylist && node->pkt->pkttype == PKT_PUBLIC_KEY )
BUG(); /* more than one primary key */
fingerprint = fingerprint_from_pk( orig_pk, &fingerlen );
rec = m_alloc_clear( sizeof *rec );
rec->r.key.pubkey_algo = pk->pubkey_algo;
rec->r.key.fingerprint_len = fingerlen;
memcpy(rec->r.key.fingerprint, fingerprint, fingerlen );
if( keylist )
keylist_tail = &keylist->next;
*keylist_tail = keylist = rec;
}
else if( node->pkt->pkttype == PKT_USER_ID ) {
PKT_user_id *uid = node->pkt->pkt.user_id;
rec = m_alloc_clear( sizeof *rec );
rmd160_hash_buffer( rec->r.uid.namehash, uid->name, uid->len );
if( uidlist )
uidlist_tail = &uidlist->next;
*uidlist_tail = uidlist = rec;
}
if( node->pkt->pkttype == PKT_SIGNATURE
&& ( (node->pkt->pkt.signature->sig_class&~3) == 0x10
|| node->pkt->pkt.signature->sig_class == 0x20
|| node->pkt->pkt.signature->sig_class == 0x30) ) {
int selfsig;
rc = check_key_signature( keyblock, node, &selfsig );
if( !rc ) {
rc = set_signature_packets_local_id( node->pkt->pkt.signature );
if( rc )
log_fatal("set_signature_packets_local_id failed: %s\n",
g10_errstr(rc));
if( selfsig ) {
node->flag |= 2; /* mark signature valid */
*selfsig_okay = 1;
}
else if( node->pkt->pkt.signature->sig_class == 0x20 )
*revoked = 1;
else
node->flag |= 1; /* mark signature valid */
if( node->pkt->pkt.signature->sig_class != 0x20 ) {
if( !dups )
dups = new_lid_table();
if( ins_lid_table_item( dups,
node->pkt->pkt.signature->local_id, 0) )
node->flag |= 4; /* mark as duplicate */
}
}
if( DBG_TRUST )
log_debug("trustdb: sig from %08lX.%lu: %s%s\n",
(ulong)node->pkt->pkt.signature->keyid[1],
node->pkt->pkt.signature->local_id,
g10_errstr(rc), (node->flag&4)?" (dup)":"" );
}
}
/* fixme: assert that we do not have this record. */
dnum = tdbio_new_recnum();
knum = tdbio_new_recnum();
/* build dir record */
memset( &rec, 0, sizeof rec );
@ -1451,10 +1568,6 @@ insert_trust_record( PKT_public_key *pk )
rec.r.dir.keyid[1] = keyid[1];
rec.r.dir.keyrec = knum;
rec.r.dir.no_sigs = 0;
if( tdbio_write_record( dnum, &rec ) ) {
log_error("writing dir record failed\n");
return G10ERR_TRUSTDB;
}
/* and the key record */
memset( &rec, 0, sizeof rec );
rec.rectype = RECTYPE_KEY;
@ -1469,8 +1582,14 @@ insert_trust_record( PKT_public_key *pk )
log_error("wrinting key record failed\n");
return G10ERR_TRUSTDB;
}
if( tdbio_write_record( dirrec.r.dir.lid, &dirrec ) ) {
log_error("writing dir record failed\n");
return G10ERR_TRUSTDB;
}
/* and store the LID */
pk->local_id = dnum;
orig_pk->local_id = dnum;
return 0;
}
@ -1504,27 +1623,5 @@ update_ownertrust( ulong lid, unsigned new_trust )
/****************
* Kludge to prevent duplicate build_sigrecs() due to an invalid
* certificate (no selfsignature or something like this)
*/
static int
update_no_sigs( ulong lid, int no_sigs )
{
TRUSTREC rec;
if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) {
log_error("update_no_sigs: read failed\n");
return G10ERR_TRUSTDB;
}
rec.r.dir.no_sigs = no_sigs;
if( tdbio_write_record( lid, &rec ) ) {
log_error("update_no_sigs: write failed\n");
return G10ERR_TRUSTDB;
}
return 0;
}

View File

@ -77,7 +77,7 @@ verify_signatures( int nfiles, char **files )
sl = NULL;
for(i=1 ; i < nfiles; i++ )
add_to_strlist( &sl, files[i] );
rc = proc_signature_packets( fp, sl );
rc = proc_signature_packets( fp, sl, sigfile );
free_strlist(sl);
iobuf_close(fp);
return rc;

View File

@ -1,3 +1,7 @@
Thu Jul 9 21:14:51 1998 Werner Koch (wk@isil.d.shuttle.de)
* de.po: Fixed typos and added new translations.
Fri Jun 26 11:44:24 1998 Werner Koch (wk@isil.d.shuttle.de)
* it.po: New file from Marco.

Binary file not shown.

View File

@ -92,7 +92,7 @@ POSUB = po
RANLIB = ranlib
USE_INCLUDED_LIBINTL = yes
USE_NLS = yes
VERSION = 0.3.2
VERSION = 0.3.2b
ZLIBS =
l =