diff options
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | NEWS | 10 | ||||
-rw-r--r-- | README | 134 | ||||
-rw-r--r-- | THANKS | 1 | ||||
-rw-r--r-- | TODO | 26 | ||||
-rw-r--r-- | VERSION | 2 | ||||
-rwxr-xr-x | checks/defs.inc | 4 | ||||
-rw-r--r-- | cipher/ChangeLog | 5 | ||||
-rw-r--r-- | cipher/primegen.c | 1 | ||||
-rw-r--r-- | cipher/random.c | 4 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | doc/DETAILS | 130 | ||||
-rw-r--r-- | doc/Makefile.am | 2 | ||||
-rw-r--r-- | doc/gpg.1pod | 5 | ||||
-rw-r--r-- | g10/ChangeLog | 32 | ||||
-rw-r--r-- | g10/OPTIONS | 13 | ||||
-rw-r--r-- | g10/armor.c | 27 | ||||
-rw-r--r-- | g10/g10.c | 32 | ||||
-rw-r--r-- | g10/getkey.c | 4 | ||||
-rw-r--r-- | g10/keydb.h | 8 | ||||
-rw-r--r-- | g10/keyedit.c | 4 | ||||
-rw-r--r-- | g10/keygen.c | 6 | ||||
-rw-r--r-- | g10/keyid.c | 24 | ||||
-rw-r--r-- | g10/keylist.c | 4 | ||||
-rw-r--r-- | g10/main.h | 4 | ||||
-rw-r--r-- | g10/mainproc.c | 27 | ||||
-rw-r--r-- | g10/misc.c | 22 | ||||
-rw-r--r-- | g10/openfile.c | 2 | ||||
-rw-r--r-- | g10/options.h | 1 | ||||
-rw-r--r-- | g10/packet.h | 2 | ||||
-rw-r--r-- | g10/pkclist.c | 8 | ||||
-rw-r--r-- | g10/plaintext.c | 45 | ||||
-rw-r--r-- | g10/seskey.c | 1 | ||||
-rw-r--r-- | g10/sign.c | 2 | ||||
-rw-r--r-- | g10/tdbio.c | 234 | ||||
-rw-r--r-- | g10/tdbio.h | 70 | ||||
-rw-r--r-- | g10/trustdb.c | 255 | ||||
-rw-r--r-- | g10/verify.c | 2 | ||||
-rw-r--r-- | po/ChangeLog | 4 | ||||
-rwxr-xr-x | tools/mk-tdata | bin | 26204 -> 35443 bytes | |||
-rw-r--r-- | zlib/Makefile | 2 |
41 files changed, 708 insertions, 456 deletions
diff --git a/Makefile.am b/Makefile.am index cd8ae7f6a..b8f6282bf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 @@ -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) @@ -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----- @@ -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 @@ -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 - @@ -1 +1 @@ -0.3.2 +0.3.2b diff --git a/checks/defs.inc b/checks/defs.inc index 61e07ee5c..f3ff66f18 100755 --- a/checks/defs.inc +++ b/checks/defs.inc @@ -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="" diff --git a/cipher/ChangeLog b/cipher/ChangeLog index bee034920..010952863 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -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 diff --git a/cipher/primegen.c b/cipher/primegen.c index 23aa1dbe8..66d40dbfc 100644 --- a/cipher/primegen.c +++ b/cipher/primegen.c @@ -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 ); diff --git a/cipher/random.c b/cipher/random.c index f44e4c3af..75754cd01 100644 --- a/cipher/random.c +++ b/cipher/random.c @@ -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); diff --git a/configure.in b/configure.in index 005a1b5fb..80a5c07dd 100644 --- a/configure.in +++ b/configure.in @@ -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 diff --git a/doc/DETAILS b/doc/DETAILS index a2de34306..1be782a1d 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -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 diff --git a/doc/Makefile.am b/doc/Makefile.am index 020338b40..dc2ee585b 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -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 diff --git a/doc/gpg.1pod b/doc/gpg.1pod index 726e97696..1fde885fa 100644 --- a/doc/gpg.1pod +++ b/doc/gpg.1pod @@ -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. diff --git a/g10/ChangeLog b/g10/ChangeLog index a637ac9e9..f6f935a57 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -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. diff --git a/g10/OPTIONS b/g10/OPTIONS index 3abe296d8..8e9cf8a6c 100644 --- a/g10/OPTIONS +++ b/g10/OPTIONS @@ -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. diff --git a/g10/armor.c b/g10/armor.c index 46151eae8..45f962f01 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -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; } @@ -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 */ diff --git a/g10/getkey.c b/g10/getkey.c index 3f8ac63b8..b73a00616 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -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 diff --git a/g10/keydb.h b/g10/keydb.h index 58a170d27..a0398092a 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -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 ); diff --git a/g10/keyedit.c b/g10/keyedit.c index ee50a7880..4369e9a86 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -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 ); diff --git a/g10/keygen.c b/g10/keygen.c index d9f8579e4..b114b8444 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -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 diff --git a/g10/keyid.c b/g10/keyid.c index 0809df93a..2e5c6aad6 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -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); } diff --git a/g10/keylist.c b/g10/keylist.c index f06b4989f..d23a98f1e 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -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++ ) diff --git a/g10/main.h b/g10/main.h index dcba0488f..fdb01343f 100644 --- a/g10/main.h +++ b/g10/main.h @@ -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); diff --git a/g10/mainproc.c b/g10/mainproc.c index 9090fd4e1..cd3e85a8b 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -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, diff --git a/g10/misc.c b/g10/misc.c index 470307363..ec7c40a1a 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -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 ) { diff --git a/g10/openfile.c b/g10/openfile.c index be2702b55..afa36b983 100644 --- a/g10/openfile.c +++ b/g10/openfile.c @@ -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); } } diff --git a/g10/options.h b/g10/options.h index 0929be328..80a6539ec 100644 --- a/g10/options.h +++ b/g10/options.h @@ -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 */ diff --git a/g10/packet.h b/g10/packet.h index 0cefd8d10..cef9afe5c 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -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 ); diff --git a/g10/pkclist.c b/g10/pkclist.c index 81e23c765..e509f0064 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -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" diff --git a/g10/plaintext.c b/g10/plaintext.c index 8d7b2a97e..1a22ecdbd 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -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); } diff --git a/g10/seskey.c b/g10/seskey.c index 5b271a2d4..6e76d12db 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -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)) ) ; diff --git a/g10/sign.c b/g10/sign.c index 14dfe417e..6192d5987 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -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 ); diff --git a/g10/tdbio.c b/g10/tdbio.c index d3b9a7221..425e51cbb 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -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; +} + diff --git a/g10/tdbio.h b/g10/tdbio.h index facb5c307..7229d7222 100644 --- a/g10/tdbio.h +++ b/g10/tdbio.h @@ -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) | \ diff --git a/g10/trustdb.c b/g10/trustdb.c index 916eeffd1..593e12cd2 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -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; -} diff --git a/g10/verify.c b/g10/verify.c index 7a2f73130..02cc5d003 100644 --- a/g10/verify.c +++ b/g10/verify.c @@ -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; diff --git a/po/ChangeLog b/po/ChangeLog index e42ffac6d..d37483946 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -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. diff --git a/tools/mk-tdata b/tools/mk-tdata Binary files differindex 1664b3278..3b9e1c016 100755 --- a/tools/mk-tdata +++ b/tools/mk-tdata diff --git a/zlib/Makefile b/zlib/Makefile index 51a26a471..37c004567 100644 --- a/zlib/Makefile +++ b/zlib/Makefile @@ -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 = |