1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-17 14:07:03 +01:00
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; \ || cp -p $(srcdir)/$$dir/$$i $(distdir)/$$dir/$$i; \
done ; \ done ; \
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 Noteworthy changes in version 0.3.2
----------------------------------- -----------------------------------
* Fixed some bugs when using --textmode (-seat) * 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 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 still available, but due to the larger size of such signatures it
is depreciated (Please note that the GNUPG implementation of ElGamal is depreciated (Please note that the GNUPG implementation of ElGamal
signatures is *not* insecure). Symmetric algorithms are: Blowfish 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: See the file INSTALL. Here is a quick summary:
1) "./configure" 1) "./configure"
2) "make" 2) "make"
@ -75,7 +72,7 @@
Key Generation Key Generation
-------------- --------------
gpg --gen-key gpg --gen-key
This asks some questions and then starts key generation. To create This asks some questions and then starts key generation. To create
good random numbers for prime number generation, it uses a /dev/random 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 You should make a revocation certificate in case someone gets
knowledge of your secret key or you forgot your passphrase: 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, 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 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 If you decided to create a DSA key, you should add an ElGamal
for encryption: 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"). and follow the displayed instructions (select "ElGamal using v4 packets").
You can sign a key with this command: 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. 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" This let you sign the key of of "Donald" with the userids of "Karl"
and "Joe". and "Joe".
@ -117,7 +114,7 @@
whether you want to sign this key. whether you want to sign this key.
You may remove a signature at any time using the option "--edit-sig", 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 Sign
---- ----
gpg -s file gpg -s file
This creates a file file.gpg which is compressed and has a signature This creates a file file.gpg which is compressed and has a signature
attached. attached.
gpg -sa file gpg -sa file
Same as above, but file.gpg is ascii armored. 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". Creates a signature of file, but writes the output to the file "out".
@ -142,12 +139,12 @@
Encrypt Encrypt
------- -------
gpg -e -r heine file gpg -e -r heine file
This encrypts files with the public key of "heine" and writes it This encrypts files with the public key of "heine" and writes it
to "file.gpg" 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. Ditto, but encrypts "hallo\n" and mails it as ascii armored message.
@ -155,13 +152,13 @@
Sign and Encrypt 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 This encrypts files with the public key of "heine" and writes it
to "file.gpg" after signing it with the default user id. 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" Ditto, but sign the file with the user id "Suttner"
@ -170,17 +167,17 @@
------------------ ------------------
To export your complete keyring(s) do this: To export your complete keyring(s) do this:
gpg --export gpg --export
To export only some user ids do this: To export only some user ids do this:
gpg --export userids gpg --export userids
Use "-a" or "--armor" to create ASCII armored output. Use "-a" or "--armor" to create ASCII armored output.
Importing keys is done with the option, you guessed it, "--import": 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 New keys are appended to the default keyring and already existing
keys are merged. Keys without a self-signature are ignored. 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): * Only by the short keyid (prepend a zero if it begins with A..F):
"234567C4" "234567C4"
"0F34E556E" "0F34E556E"
"01347A56A" "01347A56A"
"0xAB123456 "0xAB123456
* By a complete keyid: * By a complete keyid:
"234AABBCC34567C4" "234AABBCC34567C4"
"0F323456784E56EAB" "0F323456784E56EAB"
"01AB3FED1347A5612" "01AB3FED1347A5612"
"0x234AABBCC34567C4" "0x234AABBCC34567C4"
* By a fingerprint: * By a fingerprint:
"1234343434343434C434343434343434" "1234343434343434C434343434343434"
"123434343434343C3434343434343734349A3434" "123434343434343C3434343434343734349A3434"
"0E12343434343434343434EAB3484343434343434" "0E12343434343434343434EAB3484343434343434"
The first one is MD5 the others are ripemd160 or sha1. The first one is MD5 the others are ripemd160 or sha1.
* By an exact string (not yet implemented): * By an exact string (not yet implemented):
"=Heinrich Heine <heinrichh@uni-duesseldorf.de>" "=Heinrich Heine <heinrichh@uni-duesseldorf.de>"
* By an email address: * By an email address:
"<heinrichh@uni-duesseldorf.de>" "<heinrichh@uni-duesseldorf.de>"
This can be used by a keyserver instead of a substring to This can be used by a keyserver instead of a substring to
find this key faster. find this key faster.
* By the Local ID (from the trustdb): * By the Local ID (from the trustdb):
"#34" "#34"
This can be used by a MUA to specify an exact key after selecting 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) a key from GNUPG (by the use of a special option or an extra utility)
@ -233,8 +230,8 @@
* Or by the usual substring: * Or by the usual substring:
"Heine" "Heine"
"*Heine" "*Heine"
The '*' indicates substring search explicitly. The '*' indicates substring search explicitly.
@ -264,21 +261,21 @@
Esoteric commands 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 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 you are asked for the passphrase, so that GNUPG is able to look at the
inner structure of a encrypted packet. inner structure of a encrypted packet.
gpgm --list-trustdb gpgm --list-trustdb
List the contents of the trustdb in a human readable format 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 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 List the possible trust paths for the given username, up to the specified
depth. If depth is negative, duplicate introducers are not listed, 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 using a negative number). This option may create new entries in the
trustdb. trustdb.
gpgm --print-mds filenames gpgm --print-mds filenames
List all available message digest values for the fiven 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" 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 can be used multiple times, all values are ORed; n maybe prefixed with
0x to use hex-values. 0x to use hex-values.
value used for value used for
----- ---------------------------------------------- ----- ----------------------------------------------
1 packet reading/writing 1 packet reading/writing
2 MPI details 2 MPI details
4 ciphers and primes (may reveal sensitive data) 4 ciphers and primes (may reveal sensitive data)
8 iobuf filter functions 8 iobuf filter functions
16 iobuf stuff 16 iobuf stuff
32 memory allocation stuff 32 memory allocation stuff
64 caching 64 caching
128 show memory statistics at exit 128 show memory statistics at exit
256 trust verification stuff 256 trust verification stuff
Other Notes Other Notes
@ -342,14 +325,3 @@
post them to the mailing list <g10@net.lut.ac.uk> (this is a closed list, post them to the mailing list <g10@net.lut.ac.uk> (this is a closed list,
please subscribe before posting). 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 Mark Adler madler@alumni.caltech.edu
Martin Schulte schulte@thp.uni-koeln.de Martin Schulte schulte@thp.uni-koeln.de
Matthew Skala mskala@ansuz.sooke.bc.ca Matthew Skala mskala@ansuz.sooke.bc.ca
Max Valianskiy maxcom@maxcom.ml.org
Nicolas Graner Nicolas.Graner@cri.u-psud.fr Nicolas Graner Nicolas.Graner@cri.u-psud.fr
Peter Gutmann pgut001@cs.auckland.ac.nz Peter Gutmann pgut001@cs.auckland.ac.nz
Ralph Gillen gillen@theochem.uni-duesseldorf.de 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 * what about the CR,LF in cleartext singatures?
* Change the inernal represenation of keyid into a struct which
can also hold the localid
* add option --restore-ownertrust * add option --restore-ownertrust
* always put key signatures before the first subkey. * 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?) * add a way to delete subkeys (in edit-keys?)
* make preferences work * make preferences work
* rewrite --list-packets or put it into another tool. * 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 * add usage arguments to get_key_byname or return a PKC_LIST with
all keys and add a selection. all keys and add a selection.
@ -28,14 +24,9 @@
* Burn the buffers used by fopen(), or use read(2). Does this * Burn the buffers used by fopen(), or use read(2). Does this
really make sense? really make sense?
* enable a SIGSEGV handler while using zlib functions * enable a SIGSEGV handler while using zlib functions
* improve iobuf by reading more than one byte at once, * Change the buffering to a mbuf like scheme? Need it for PSST anyway.
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.
* add checking of armor trailers * add checking of armor trailers
* remove all "Fixmes" * remove all "Fixmes"
@ -50,10 +41,5 @@
* add an option to re-create a public key from a secret key. Think about * 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. 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 * 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" 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-32000 data-80000"
data_files="data-500 data-9000" #data_files="data-500 data-9000"
exp_files="" 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) Thu Jul 9 13:01:14 1998 Werner Koch (wk@isil.d.shuttle.de)
* dynload.c (load_extension): Function now nbails out if * 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 ); mods = m_alloc( no_of_small_prime_numbers * sizeof *mods );
/* make nbits fit into MPI implementation */ /* make nbits fit into MPI implementation */
nlimbs = (nbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB; nlimbs = (nbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB;
assert( nlimbs );
val_2 = mpi_alloc( nlimbs ); val_2 = mpi_alloc( nlimbs );
mpi_set_ui(val_2, 2); mpi_set_ui(val_2, 2);
val_3 = mpi_alloc( nlimbs ); 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; size_t nbytes = (nbits+7)/8;
MASK_LEVEL(level); 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 ); read_pool( buf, nbytes, level );
return buf; return buf;
} }
@ -222,7 +222,7 @@ read_pool( byte *buffer, size_t length, int level )
needed = length - pool_balance; needed = length - pool_balance;
if( needed > POOLSIZE ) if( needed > POOLSIZE )
BUG(); 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 */ read_random_source( p, needed, 2 ); /* read /dev/random */
add_randomness( p, needed, 3); add_randomness( p, needed, 3);
m_free(p); m_free(p);

View File

@ -182,7 +182,7 @@ fi
dnl Checks for library functions. dnl Checks for library functions.
AC_FUNC_VPRINTF AC_FUNC_VPRINTF
AC_CHECK_FUNCS(strerror stpcpy strlwr tcgetattr rand strtoul mlock mmap) 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 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 Version information for this TrustDB. This is always the first
record of the DB and the only one with type 1. record of the DB and the only one with type 1.
1 byte value 1 1 byte value 2
3 bytes 'gpg' magic value 3 bytes 'gpg' magic value
1 byte Version of the TrustDB 1 byte Version of the TrustDB
3 byte reserved 3 byte reserved
@ -81,42 +81,79 @@ Record type 2: (directory record)
These are static values which are never changed without user interaction. These are static values which are never changed without user interaction.
1 byte value 2 1 byte value 2
1 byte reserved 1 byte reserved
8 bytes keyid (We keep it here to speed up searching by keyid) 1 u32 LID . (This is simply the record number of this record.)
1 u32 Local-Id. This is simply the record number of this record. 1 u32 List of key-records (the first one is the primary key)
1 u32 primary public key (record number of it) 1 u32 List of uid-records
1 u32 cache record 1 u32 cache record
1 u32 sigrecord 1 byte ownertrust
1 byte No signatures flag (used to avoid duplicate building). 1 byte sigflag
3 byte reserved 20 byte reserved
1 u32 userid record
6 byte reserved
Record type 3: Record type 3: (key record)
-------------- --------------
Informations about a primary public key. 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 value 3
1 byte reserved 1 byte reserved
1 u32 owner This is used to bind all records for 1 u32 LID
a given certificate together. It is valid only in this TrustDB 1 u32 next - next key record
and useful if we have duplicate keyids 8 bytes reserved
It points back to the directory node. 1 byte pubkey algorithm
1 byte pubkey algorithm 1 byte length of the fingerprint (in bytes)
1 byte length of the fingerprint (in bytes)
20 bytes fingerprint of the public key 20 bytes fingerprint of the public key
1 byte ownertrust if there is no trust defined for the userid: (This is the value we use to identify a key)
3 byte reserved
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 Used to bind the trustDB to the concrete instance of keyblock in
a pubring. This is used to cache information. a pubring. This is used to cache information.
1 byte value 4 1 byte value 9
1 byte reserved 1 byte reserved
1 u32 Local-Id. 1 u32 Local-Id.
8 bytes keyid of the primary key (needed?) 8 bytes keyid of the primary key (needed?)
@ -141,23 +178,9 @@ Record type 4: (cache record)
4 = fully trusted 4 = fully trusted
5 = ultimately trusted (have secret key too). 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 Record Type 10 (hash table)
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)
-------------
Due to the fact that we use the keyid to lookup keys, we can Due to the fact that we use the keyid to lookup keys, we can
implement quick access by some simple hash methods, and avoid implement quick access by some simple hash methods, and avoid
the overhead of gdbm. A property of keyids is that they can be 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 big table. The hash value is simple the 1st, 2nd, ... byte of
the keyid (depending on the indirection level). the keyid (depending on the indirection level).
1 byte value 5 1 byte value 10
1 byte reserved 1 byte reserved
n u32 recnum; n depends on th record length: n u32 recnum; n depends on th record length:
n = (reclen-2)/4 which yields 9 for the current 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 if this is not the correct dir record, we look at the next
dir record which is linked by the link field. 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. see hash table for an explanation.
1 byte value 6 1 byte value 11
1 byte reserved 1 byte reserved
1 u32 chain next hash list record 1 u32 next next hash list record
n times n = (reclen-6)/5 n times n = (reclen-6)/5
1 byte hash 1 byte hash
1 u32 recnum 1 u32 recnum
For the current record length of 40, n is 6 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 Packet Headers

View File

@ -1,6 +1,6 @@
## Process this file with automake to create Makefile.in ## 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 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 detached signature when not used in batch mode). If
only a sigfile is given, it may be a complete signature only a sigfile is given, it may be a complete signature
or a detached signature, in which case the signed stuff 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 first should be a detached signature and the remaining
files are the signed stuff. 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) Thu Jul 9 14:52:47 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (build_list): Now drops setuid. * g10.c (build_list): Now drops setuid.

View File

@ -17,15 +17,7 @@
#----------------------------------------------- #-----------------------------------------------
#------------------- Commands ------------------ #------------------- Commands ------------------
#----------------------------------------------- #-----------------------------------------------
# With some expections, these cannot be combined # With some exceptions, 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.
print-md algo print-md algo
# print the message digest of algorithm ALGO for stdin or all # 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 # algorithm with --compress-algo" - Default is to not compress keys, as
# this is better for interoperability. # 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, fhdrSKIPHeader,
fhdrCLEARSIG, fhdrCLEARSIG,
fhdrREADClearsig, fhdrREADClearsig,
fhdrNullClearsig,
fhdrEMPTYClearsig, fhdrEMPTYClearsig,
fhdrCHECKClearsig, fhdrCHECKClearsig,
fhdrCHECKClearsig2, fhdrCHECKClearsig2,
@ -343,6 +344,8 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
*r_hashes |= hashes; *r_hashes |= hashes;
} }
} }
else if( clearsig && n > 15 && !memcmp(buf, "-----", 5 ) )
state = fhdrNullClearsig;
else else
state = fhdrCHECKDashEscaped3; state = fhdrCHECKDashEscaped3;
} }
@ -386,7 +389,10 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
buf[n++] = c; buf[n++] = c;
if( n < buflen || c == '\n' ) { if( n < buflen || c == '\n' ) {
buf[n] = 0; buf[n] = 0;
state = fhdrCHECKDashEscaped3; if( n > 15 && !memcmp(buf, "-----", 5 ) )
state = fhdrNullClearsig;
else
state = fhdrCHECKDashEscaped3;
} }
else { else {
/* fixme: we should check whether this line continues /* 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; break;
case fhdrNullClearsig: /* zero length cleartext */
state = fhdrENDClearsig;
break;
case fhdrENDClearsig: case fhdrENDClearsig:
case fhdrCHECKBegin: case fhdrCHECKBegin:
state = state == fhdrCHECKBegin ? fhdrINITSkip : fhdrERRORShow; state = state == fhdrCHECKBegin ? fhdrINITSkip : fhdrERRORShow;
@ -587,10 +597,8 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
buf[1] = '\n'; buf[1] = '\n';
n = 2; n = 2;
} }
} }
*r_buflen = n; *r_buflen = n;
*r_empty = empty; *r_empty = empty;
return state; return state;
@ -627,6 +635,7 @@ check_input( armor_filter_context_t *afx, IOBUF a )
rc = -1; rc = -1;
break; break;
case fhdrNullClearsig:
case fhdrCLEARSIG: /* start fake package mode (for clear signatures) */ case fhdrCLEARSIG: /* start fake package mode (for clear signatures) */
afx->helplen = n; afx->helplen = n;
afx->helpidx = 0; afx->helpidx = 0;
@ -679,7 +688,8 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
rc = -1; rc = -1;
continue; continue;
} }
if( afx->helpidx < afx->helplen ) { /* flush the last buffer */ if( state != fhdrNullClearsig
&& afx->helpidx < afx->helplen ) { /* flush the last buffer */
n = afx->helplen; n = afx->helplen;
for(nn=afx->helpidx; len < size && nn < n ; nn++ ) for(nn=afx->helpidx; len < size && nn < n ; nn++ )
buf[len++] = afx->helpbuf[nn]; buf[len++] = afx->helpbuf[nn];
@ -693,7 +703,8 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
/* read a new one */ /* read a new one */
n = DIM(afx->helpbuf); n = DIM(afx->helpbuf);
afx->helpidx = 0; 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 ); &emplines, &afx->hashes );
switch( state) { switch( state) {
case fhdrERROR: case fhdrERROR:
@ -723,8 +734,10 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
buf[0] = (len-2) >> 8; buf[0] = (len-2) >> 8;
buf[1] = (len-2); buf[1] = (len-2);
if( state == fhdrENDClearsig ) { /* write last (ending) length header */ if( state == fhdrENDClearsig ) { /* write last (ending) length header */
buf[len++] = 0; if( buf[0] || buf[1] ) { /* write only if length of text is > 0 */
buf[len++] = 0; buf[len++] = 0;
buf[len++] = 0;
}
rc = 0; rc = 0;
} }

View File

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

View File

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

View File

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

View File

@ -45,7 +45,7 @@ show_fingerprint( PKT_public_key *pk )
byte *array, *p; byte *array, *p;
size_t i, n; size_t i, n;
p = array = fingerprint_from_pk( pk, &n ); p = array = fingerprint_from_pk( pk, NULL, &n );
tty_printf(" Fingerprint:"); tty_printf(" Fingerprint:");
if( n == 20 ) { if( n == 20 ) {
for(i=0; i < n ; i++, i++, p += 2 ) { for(i=0; i < n ; i++, i++, p += 2 ) {
@ -292,7 +292,7 @@ sign_key( const char *username, STRLIST locusr )
if( !opt.batch ) { if( !opt.batch ) {
/* ask whether we really should do anything */ /* ask whether we really should do anything */
answer = tty_get( 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(); tty_kill_prompt();
if( answer_is_yes(answer) ) if( answer_is_yes(answer) )
remove_keysigs( keyblock, pk_keyid, 0 ); remove_keysigs( keyblock, pk_keyid, 0 );

View File

@ -442,9 +442,9 @@ ask_keysize( int algo )
else if( nbits < 768 ) else if( nbits < 768 )
tty_printf(_("keysize too small; 768 is smallest value allowed.\n")); tty_printf(_("keysize too small; 768 is smallest value allowed.\n"));
else if( nbits > 2048 ) { 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")); "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(); tty_kill_prompt();
if( answer_is_yes(answer) ) { if( answer_is_yes(answer) ) {
m_free(answer); m_free(answer);
@ -685,7 +685,7 @@ ask_passphrase( STRING2KEY **ret_s2k )
tty_printf(_( tty_printf(_(
"You don't want a passphrase - this is probably a *bad* idea!\n" "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" "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; break;
} }
else 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 * 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 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 * 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; const char *dp;
size_t len; size_t len;
unsigned n; unsigned n;
@ -287,7 +287,8 @@ fingerprint_from_pk( PKT_public_key *pk, size_t *ret_len )
m_free(buf); m_free(buf);
} }
md_final(md); md_final(md);
array = m_alloc( 16 ); if( !array )
array = m_alloc( 16 );
len = 16; len = 16;
memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 ); memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 );
md_close(md); md_close(md);
@ -297,7 +298,9 @@ fingerprint_from_pk( PKT_public_key *pk, size_t *ret_len )
md = do_fingerprint_md(pk); md = do_fingerprint_md(pk);
dp = md_read( md, 0 ); dp = md_read( md, 0 );
len = md_digest_length( md_get_algo( md ) ); 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 ); memcpy(array, dp, len );
md_close(md); md_close(md);
} }
@ -307,9 +310,9 @@ fingerprint_from_pk( PKT_public_key *pk, size_t *ret_len )
} }
byte * 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; const char *dp;
size_t len; size_t len;
unsigned n; unsigned n;
@ -328,7 +331,8 @@ fingerprint_from_sk( PKT_secret_key *sk, size_t *ret_len )
m_free(buf); m_free(buf);
} }
md_final(md); md_final(md);
array = m_alloc( 16 ); if( !array )
array = m_alloc( 16 );
len = 16; len = 16;
memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 ); memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 );
md_close(md); md_close(md);
@ -338,7 +342,9 @@ fingerprint_from_sk( PKT_secret_key *sk, size_t *ret_len )
md = do_fingerprint_md_sk(sk); md = do_fingerprint_md_sk(sk);
dp = md_read( md, 0 ); dp = md_read( md, 0 );
len = md_digest_length( md_get_algo( md ) ); 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 ); memcpy(array, dp, len );
md_close(md); md_close(md);
} }

View File

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

View File

@ -47,6 +47,7 @@ void do_not_use_RSA(void);
/*-- misc.c --*/ /*-- misc.c --*/
void trap_unaligned(void); void trap_unaligned(void);
void disable_core_dumps(void);
u16 checksum_u16( unsigned n ); u16 checksum_u16( unsigned n );
u16 checksum( byte *p, unsigned n ); u16 checksum( byte *p, unsigned n );
u16 checksum_mpi( MPI a ); u16 checksum_mpi( MPI a );
@ -119,7 +120,8 @@ int verify_signatures( int nfiles, char **files );
int decrypt_message( const char *filename ); int decrypt_message( const char *filename );
/*-- plaintext.c --*/ /*-- 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 --*/ /*-- signal.c --*/
void init_signals(void); void init_signals(void);

View File

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

View File

@ -22,10 +22,15 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <errno.h>
#if defined(__linux__) && defined(__alpha__) #if defined(__linux__) && defined(__alpha__)
#include <asm/sysinfo.h> #include <asm/sysinfo.h>
#include <asm/unistd.h> #include <asm/unistd.h>
#endif #endif
#ifdef HAVE_SETRLIMIT
#include <sys/time.h>
#include <sys/resource.h>
#endif
#include "util.h" #include "util.h"
#include "main.h" #include "main.h"
#include "options.h" #include "options.h"
@ -70,6 +75,23 @@ trap_unaligned(void)
#endif #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 u16
checksum_u16( unsigned n ) checksum_u16( unsigned n )
{ {

View File

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

View File

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

View File

@ -222,7 +222,7 @@ typedef enum {
/*-- mainproc.c --*/ /*-- mainproc.c --*/
int proc_packets( IOBUF a ); 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 proc_encryption_packets( IOBUF a );
int list_packets( IOBUF a ); int list_packets( IOBUF a );

View File

@ -63,7 +63,7 @@ query_ownertrust( ulong lid )
return 0; return 0;
} }
tty_printf(_("No ownertrust defined for %lu:\n" tty_printf(_("No owner trust defined for %lu:\n"
"%4u%c/%08lX %s \""), lid, "%4u%c/%08lX %s \""), lid,
nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ), nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ),
(ulong)keyid[1], datestr_from_pk( pk ) ); (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 )) ) { while( !(rc=enum_trust_web( &context, &lid )) ) {
rc = get_ownertrust( lid, &trust ); rc = get_ownertrust( lid, &trust );
if( rc ) 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 || if( trust == TRUST_UNDEFINED || trust == TRUST_EXPIRED ||
trust == TRUST_UNKNOWN ) { trust == TRUST_UNKNOWN ) {
if( query_ownertrust( lid ) ) 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 */ enum_trust_web( &context, NULL ); /* close */
if( !any ) 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; return rc? rc : any? 0:-1;
} }
@ -366,7 +366,7 @@ check_signatures_trust( PKT_signature *sig )
case TRUST_MARGINAL: case TRUST_MARGINAL:
write_status( STATUS_TRUST_MARGINAL ); write_status( STATUS_TRUST_MARGINAL );
log_info(_( 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(_( log_info(_(
" It is not certain that the signature belongs to the owner.\n" " 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 */ /* no filename or "-" given; write to stdout */
fp = stdout; fp = stdout;
} }
else if( overwrite_filep( fname ) ) else if( (rc=overwrite_filep( fname )) ) {
if( rc == -1 )
rc = G10ERR_CREATE_FILE;
goto leave; goto leave;
}
if( fp || nooutput ) if( fp || nooutput )
; ;
else if( !(fp = fopen(fname,"wb")) ) { else if( !(fp = fopen(fname,"wb")) ) {
log_error("Error creating '%s': %s\n", fname, strerror(errno) ); log_error("Error creating '%s': %s\n", fname, strerror(errno) );
rc = G10ERR_WRITE_FILE; rc = G10ERR_CREATE_FILE;
goto leave; 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. * Hash the given files and append the hash to hash context md.
* If FILES is NULL, hash stdin. * If FILES is NULL, hash stdin.
*/ */
int int
hash_datafiles( MD_HANDLE md, STRLIST files, int textmode ) hash_datafiles( MD_HANDLE md, STRLIST files,
const char *sigfilename, int textmode )
{ {
IOBUF fp; IOBUF fp;
STRLIST sl=NULL; 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, "-"); add_to_strlist( &sl, "-");
}
else else
sl = files; sl = files;
@ -271,12 +297,7 @@ hash_datafiles( MD_HANDLE md, STRLIST files, int textmode )
free_strlist(sl); free_strlist(sl);
return G10ERR_OPEN_FILE; return G10ERR_OPEN_FILE;
} }
if( textmode ) { do_hash( md, fp, textmode );
memset( &tfx, 0, sizeof tfx);
iobuf_push_filter( fp, text_filter, &tfx );
}
while( (c = iobuf_get(fp)) != -1 )
md_putc(md, c );
iobuf_close(fp); iobuf_close(fp);
} }

View File

@ -86,6 +86,7 @@ encode_session_key( DEK *dek, unsigned nbits )
frame[n++] = 2; frame[n++] = 2;
i = nframe - 6 - dek->keylen; i = nframe - 6 - dek->keylen;
assert( i > 0 ); assert( i > 0 );
/* FIXME: replace the loop by a call to get_random_bits() */
for( ; i ; i-- ) { for( ; i ; i-- ) {
while( !(c = get_random_byte(1)) ) 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 ); iobuf_push_filter( out, encrypt_filter, &efx );
} }
if( opt.compress && !outfile ) { if( opt.compress && !outfile && ( !detached || opt.compress_sigs) ) {
if( old_style ) if( old_style )
zfx.algo = 1; zfx.algo = 1;
iobuf_push_filter( out, compress_filter, &zfx ); iobuf_push_filter( out, compress_filter, &zfx );

View File

@ -147,7 +147,7 @@ create_db( const char *fname )
fp =fopen( fname, "w" ); fp =fopen( fname, "w" );
if( !fp ) if( !fp )
log_fatal_f( fname, _("can't create %s: %s\n"), strerror(errno) ); 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, 'g' );
fwrite_8( fp, 'p' ); fwrite_8( fp, 'p' );
fwrite_8( fp, 'g' ); fwrite_8( fp, 'g' );
@ -195,55 +195,67 @@ tdbio_dump_record( ulong rnum, TRUSTREC *rec, FILE *fp )
case RECTYPE_VER: fprintf(fp, "version\n"); case RECTYPE_VER: fprintf(fp, "version\n");
break; break;
case RECTYPE_DIR: case RECTYPE_DIR:
fprintf(fp, "dir keyid=%08lX, key=%lu, ctl=%lu, sig=%lu", fprintf(fp, "dir %lu, keys=%lu, uids=%lu, cach=%lu, ot=%02x",
(ulong)rec->r.dir.keyid[1], rec->r.dir.lid,
rec->r.dir.keyrec, rec->r.dir.ctlrec, rec->r.dir.sigrec ); rec->r.dir.keylist,
if( rec->r.dir.no_sigs == 1 ) rec->r.dir.uidlist,
rec->r.dir.cacherec,
rec->r.dir.ownertrust );
if( rec->r.dir.sigflag == 1 )
fputs(", (none)", fp ); fputs(", (none)", fp );
else if( rec->r.dir.no_sigs == 2 ) else if( rec->r.dir.sigflag == 2 )
fputs(", (invalid)", fp ); fputs(", (invalid)", fp );
else if( rec->r.dir.no_sigs == 3 ) else if( rec->r.dir.sigflag == 3 )
fputs(", (revoked)", fp ); fputs(", (revoked)", fp );
else if( rec->r.dir.no_sigs ) else if( rec->r.dir.sigflag )
fputs(", (??)", fp ); fputs(", (??)", fp );
putc('\n', fp); putc('\n', fp);
break; break;
case RECTYPE_KEY: fprintf(fp, case RECTYPE_KEY:
"key %08lX, own=%lu, ownertrust=%02x, fl=%d\n", fprintf(fp, "key %lu, next=%lu, algo=%d, flen=%d\n",
(ulong)rec->r.key.keyid[1], rec->r.key.lid,
rec->r.key.owner, rec->r.key.ownertrust, rec->r.key.next,
rec->r.key.pubkey_algo,
rec->r.key.fingerprint_len ); rec->r.key.fingerprint_len );
break; break;
case RECTYPE_UID: case RECTYPE_UID:
if( !rec->r.uid.subtype ) fprintf(fp, "uid %lu, next=%lu, pref=%lu, sig=%lu, hash=%02X%02X\n",
fprintf(fp, rec->r.uid.lid,
"uid %02x%02x, owner=%lu, chain=%lu, pref=%lu, otr=%02x\n", rec->r.uid.next,
rec->r.uid.namehash[18], rec->r.uid.namehash[19], rec->r.uid.prefrec,
rec->r.uid.owner, rec->r.uid.chain, (ulong)rec->r.uid.prefrec, rec->r.uid.siglist,
rec->r.uid.ownertrust ); rec->r.uid.namehash[18], rec->r.uid.namehash[19]);
else
fprintf(fp,
"uid subtype%d, owner=%lu, chain=%lu\n",
rec->r.uid.subtype, rec->r.uid.owner, rec->r.uid.chain);
break; 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; break;
case RECTYPE_SIG: case RECTYPE_SIG:
fprintf(fp, "sigrec, owner=%lu, chain=%lu\n", fprintf(fp, "sig %lu, next=%lu\n",
rec->r.sig.owner, rec->r.sig.chain ); rec->r.sig.lid, rec->r.sig.next );
for(i=any=0; i < SIGS_PER_RECORD; i++ ) { 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 ) { if( !any ) {
putc('\t', fp); putc('\t', fp);
any++; any++;
} }
fprintf(fp, " %lu:%02x", rec->r.sig.sig[i].local_id, fprintf(fp, " %lu:%02x", rec->r.sig.sig[i].lid,
rec->r.sig.sig[i].flag ); rec->r.sig.sig[i].flag );
} }
} }
if( any ) if( any )
putc('\n', fp); putc('\n', fp);
break; 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: default:
fprintf(fp, "%d (unknown)\n", rec->rectype ); fprintf(fp, "%d (unknown)\n", rec->rectype );
break; break;
@ -287,8 +299,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
case 0: /* unused record */ case 0: /* unused record */
break; break;
case RECTYPE_VER: /* version record */ case RECTYPE_VER: /* version record */
/* g10 was the original name */ if( memcmp(buf+1, "gpg", 3 ) ) {
if( memcmp(buf+1, "gpg", 3 ) && memcmp(buf+1, "g10", 3 ) ) {
log_error_f( db_name, _("not a trustdb file\n") ); log_error_f( db_name, _("not a trustdb file\n") );
rc = G10ERR_TRUSTDB; rc = G10ERR_TRUSTDB;
} }
@ -306,51 +317,60 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
(ulong)recnum ); (ulong)recnum );
rc = G10ERR_TRUSTDB; 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", log_error_f( db_name, "invalid file version %d\n",
rec->r.ver.version ); rec->r.ver.version );
rc = G10ERR_TRUSTDB; rc = G10ERR_TRUSTDB;
} }
break; break;
case RECTYPE_DIR: /*directory record */ case RECTYPE_DIR: /*directory record */
rec->r.dir.local_id = buftoulong(p); p += 4; rec->r.dir.lid = buftoulong(p); p += 4;
rec->r.dir.keyid[0] = buftou32(p); p += 4; rec->r.dir.keylist = buftoulong(p); p += 4;
rec->r.dir.keyid[1] = buftou32(p); p += 4; rec->r.dir.uidlist = buftoulong(p); p += 4;
rec->r.dir.keyrec = buftoulong(p); p += 4; rec->r.dir.cacherec = buftoulong(p); p += 4;
rec->r.dir.ctlrec = buftoulong(p); p += 4; rec->r.dir.ownertrust = *p++;
rec->r.dir.sigrec = buftoulong(p); p += 4; rec->r.dir.sigflag = *p++;
rec->r.dir.no_sigs = *p++; if( rec->r.dir.lid != recnum ) {
if( rec->r.dir.local_id != recnum ) { log_error_f( db_name, "dir LID != recnum (%lu,%lu)\n",
log_error_f( db_name, "dir local_id != recnum (%lu,%lu)\n", rec->r.dir.lid, (ulong)recnum );
(ulong)rec->r.dir.local_id,
(ulong)recnum );
rc = G10ERR_TRUSTDB; rc = G10ERR_TRUSTDB;
} }
break; break;
case RECTYPE_KEY: /* public key record */ case RECTYPE_KEY: /* public key record */
rec->r.key.owner = buftoulong(p); p += 4; rec->r.key.lid = buftoulong(p); p += 4;
rec->r.dir.keyid[0] = buftou32(p); p += 4; rec->r.key.next = buftoulong(p); p += 4;
rec->r.dir.keyid[1] = buftou32(p); p += 4; p += 8;
rec->r.key.pubkey_algo = *p++; rec->r.key.pubkey_algo = *p++;
rec->r.key.fingerprint_len = *p++; rec->r.key.fingerprint_len = *p++;
if( rec->r.key.fingerprint_len < 1 || rec->r.key.fingerprint_len > 20 ) if( rec->r.key.fingerprint_len < 1 || rec->r.key.fingerprint_len > 20 )
rec->r.key.fingerprint_len = 20; rec->r.key.fingerprint_len = 20;
memcpy( rec->r.key.fingerprint, p, 20); p += 20; memcpy( rec->r.key.fingerprint, p, 20);
rec->r.key.ownertrust = *p++;
break; break;
case RECTYPE_CTL: /* control record */ case RECTYPE_UID: /* user id record */
rec->r.ctl.owner = buftoulong(p); p += 4; rec->r.uid.lid = buftoulong(p); p += 4;
memcpy(rec->r.ctl.blockhash, p, 20); p += 20; rec->r.uid.next = buftoulong(p); p += 4;
rec->r.ctl.trustlevel = *p++; 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; break;
case RECTYPE_SIG: case RECTYPE_SIG:
rec->r.sig.owner = buftoulong(p); p += 4; rec->r.sig.lid = buftoulong(p); p += 4;
rec->r.sig.chain = buftoulong(p); p += 4; rec->r.sig.next = buftoulong(p); p += 4;
for(i=0; i < SIGS_PER_RECORD; i++ ) { 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++; rec->r.sig.sig[i].flag = *p++;
} }
break; 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: default:
log_error_f( db_name, "invalid record type %d at recnum %lu\n", log_error_f( db_name, "invalid record type %d at recnum %lu\n",
rec->rectype, (ulong)recnum ); rec->rectype, (ulong)recnum );
@ -385,40 +405,53 @@ tdbio_write_record( ulong recnum, TRUSTREC *rec )
break; break;
case RECTYPE_DIR: /*directory record */ case RECTYPE_DIR: /*directory record */
ulongtobuf(p, rec->r.dir.local_id); p += 4; ulongtobuf(p, rec->r.dir.lid); p += 4;
u32tobuf(p, rec->r.key.keyid[0]); p += 4; ulongtobuf(p, rec->r.dir.keylist); p += 4;
u32tobuf(p, rec->r.key.keyid[1]); p += 4; ulongtobuf(p, rec->r.dir.uidlist); p += 4;
ulongtobuf(p, rec->r.dir.keyrec); p += 4; ulongtobuf(p, rec->r.dir.cacherec); p += 4;
ulongtobuf(p, rec->r.dir.ctlrec); p += 4; *p++ = rec->r.dir.ownertrust;
ulongtobuf(p, rec->r.dir.sigrec); p += 4; *p++ = rec->r.dir.sigflag;
*p++ = rec->r.dir.no_sigs; assert( rec->r.dir.lid == recnum );
assert( rec->r.dir.local_id == recnum );
break; break;
case RECTYPE_KEY: case RECTYPE_KEY:
ulongtobuf(p, rec->r.key.owner); p += 4; ulongtobuf(p, rec->r.key.lid); p += 4;
u32tobuf(p, rec->r.key.keyid[0]); p += 4; ulongtobuf(p, rec->r.key.next); p += 4;
u32tobuf(p, rec->r.key.keyid[1]); p += 4; p += 8;
*p++ = rec->r.key.pubkey_algo; *p++ = rec->r.key.pubkey_algo;
*p++ = rec->r.key.fingerprint_len; *p++ = rec->r.key.fingerprint_len;
memcpy( p, rec->r.key.fingerprint, 20); p += 20; memcpy( p, rec->r.key.fingerprint, 20); p += 20;
*p++ = rec->r.key.ownertrust;
break; break;
case RECTYPE_CTL: /* control record */ case RECTYPE_UID: /* user id record */
ulongtobuf(p, rec->r.ctl.owner); p += 4; ulongtobuf(p, rec->r.uid.lid); p += 4;
memcpy(p, rec->r.ctl.blockhash, 20); p += 20; ulongtobuf(p, rec->r.uid.next); p += 4;
*p++ = rec->r.ctl.trustlevel; 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; break;
case RECTYPE_SIG: case RECTYPE_SIG:
ulongtobuf(p, rec->r.sig.owner); p += 4; ulongtobuf(p, rec->r.sig.lid); p += 4;
ulongtobuf(p, rec->r.sig.chain); p += 4; ulongtobuf(p, rec->r.sig.next); p += 4;
for(i=0; i < SIGS_PER_RECORD; i++ ) { 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; *p++ = rec->r.sig.sig[i].flag;
} }
break; 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: default:
BUG(); BUG();
} }
@ -475,7 +508,7 @@ tdbio_new_recnum()
* Note: To increase performance, we could use a index search here. * Note: To increase performance, we could use a index search here.
*/ */
int int
tdbio_search_record( PKT_public_key *pk, TRUSTREC *rec ) tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec )
{ {
ulong recnum; ulong recnum;
u32 keyid[2]; u32 keyid[2];
@ -484,30 +517,26 @@ tdbio_search_record( PKT_public_key *pk, TRUSTREC *rec )
int rc; int rc;
keyid_from_pk( pk, keyid ); keyid_from_pk( pk, keyid );
fingerprint = fingerprint_from_pk( pk, &fingerlen ); fingerprint = fingerprint_from_pk( pk, NULL, &fingerlen );
assert( fingerlen == 20 || fingerlen == 16 ); assert( fingerlen == 20 || fingerlen == 16 );
for(recnum=1; !(rc=tdbio_read_record( recnum, rec, 0)); recnum++ ) { for(recnum=1; !(rc=tdbio_read_record( recnum, rec, 0)); recnum++ ) {
if( rec->rectype != RECTYPE_DIR ) if( rec->rectype != RECTYPE_KEY )
continue; continue;
if( rec->r.dir.keyid[0] == keyid[0] if( rec->r.key.pubkey_algo == pk->pubkey_algo
&& rec->r.dir.keyid[1] == keyid[1]){ && !memcmp(rec->r.key.fingerprint, fingerprint, fingerlen) ) {
TRUSTREC keyrec; /* found: read the dir record for this key */
rc = tdbio_read_record( rec->r.key.lid, rec, RECTYPE_DIR);
if( tdbio_read_record( rec->r.dir.keyrec, &keyrec, RECTYPE_KEY ) ) { if( rc )
log_error("%lu: ooops: invalid key record\n", recnum );
break; break;
}
if( keyrec.r.key.pubkey_algo == pk->pubkey_algo if( pk->local_id && pk->local_id != recnum )
&& !memcmp(keyrec.r.key.fingerprint, fingerprint, fingerlen) ){ log_error_f(db_name,
if( pk->local_id && pk->local_id != recnum ) "found record, but LID from memory does "
log_error_f(db_name, "not match recnum (%lu,%lu)\n",
"found record, but local_id from memory does " pk->local_id, recnum );
"not match recnum (%lu,%lu)\n", pk->local_id = recnum;
(ulong)pk->local_id, (ulong)recnum ); return 0;
pk->local_id = recnum;
return 0;
}
} }
} }
if( rc != -1 ) 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_VER 1
#define RECTYPE_DIR 2 #define RECTYPE_DIR 2
#define RECTYPE_KEY 3 #define RECTYPE_KEY 3
#define RECTYPE_CTL 4 #define RECTYPE_UID 4
#define RECTYPE_SIG 5 #define RECTYPE_PREF 5
#define RECTYPE_HTBL 6 #define RECTYPE_SIG 6
#define RECTYPE_HLST 7 #define RECTYPE_CACH 9
#define RECTYPE_UID 8 #define RECTYPE_HTBL 10
#define RECTYPE_HLST 11
struct trust_record { struct trust_record {
int rectype; int rectype;
struct trust_record *next;
union { union {
struct { /* version record: */ struct { /* version record: */
byte version; /* should be 1 */ byte version; /* should be 1 */
@ -53,49 +55,50 @@ struct trust_record {
byte max_cert_depth; byte max_cert_depth;
} ver; } ver;
struct { /* directory record */ struct { /* directory record */
ulong local_id; ulong lid;
u32 keyid[2]; ulong keylist; /* List of keys (the first is the primary key)*/
ulong keyrec; /* recno of primary public key record */ ulong uidlist; /* list of uid records */
ulong ctlrec; /* recno of control record */ ulong cacherec; /* the cache record */
ulong sigrec; /* recno of first signature record (osolete) */ byte ownertrust;
ulong uidrec; /* recno of first user-id record */ byte sigflag;
ulong link; /* to next dir record */
byte no_sigs; /* does not have sigature and checked */
} dir; } dir;
struct { /* primary public key record */ struct { /* primary public key record */
ulong owner; ulong lid;
u32 keyid[2]; ulong next; /* next key */
byte pubkey_algo; byte pubkey_algo;
byte fingerprint_len; byte fingerprint_len;
byte fingerprint[20]; byte fingerprint[20];
byte ownertrust;
} key; } key;
struct { /* user id reord */ struct { /* user id reord */
ulong owner; /* point back to the directory record */ ulong lid; /* point back to the directory record */
ulong chain; /* points to next user id record */ ulong next; /* points to next user id record */
byte subtype; /* must be 0 */ ulong prefrec; /* recno of reference record */
byte namehash[20]; /* ripemd hash of the username */ ulong siglist; /* list of valid signatures (w/o self-sig)*/
byte ownertrust; byte namehash[20]; /* ripemd hash of the username */
u32 prefrec; /* recno of reference record */
} uid; } uid;
struct { /* control record */ struct { /* preference reord */
ulong owner; ulong lid; /* point back to the directory record */
byte blockhash[20]; /* or 0 for a glocal pref record */
byte trustlevel; /* calculated trustlevel */ ulong next; /* points to next pref record */
} ctl; } pref;
struct { /* signature record */ struct { /* signature record */
ulong owner; /* local_id of record owner (pubkey record) */ ulong lid;
ulong chain; /* offset of next record or NULL for last one */ ulong next; /* recnno of next record or NULL for last one */
struct { struct {
ulong local_id; /* of pubkey record of signator (0=unused) */ ulong lid; /* of pubkey record of signator (0=unused) */
byte flag; /* reserved */ byte flag; /* reserved */
} sig[SIGS_PER_RECORD]; } sig[SIGS_PER_RECORD];
} sig; } sig;
struct { /* cache record */
ulong lid;
byte blockhash[20];
byte trustlevel; /* calculated trustlevel */
} cache;
struct { struct {
ulong item[ITEMS_PER_HTBL_RECORD]; ulong item[ITEMS_PER_HTBL_RECORD];
} htbl; } htbl;
struct { struct {
ulong chain; ulong next;
struct { struct {
byte hash; byte hash;
ulong rnum; 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_read_record( ulong recnum, TRUSTREC *rec, int expected );
int tdbio_write_record( ulong recnum, TRUSTREC *rec ); int tdbio_write_record( ulong recnum, TRUSTREC *rec );
ulong tdbio_new_recnum(void); 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) | \ #define buftoulong( p ) ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \

View File

@ -42,6 +42,10 @@
#include "tdbio.h" #include "tdbio.h"
#if MAX_FINGERPRINT_LEN > 20
#error Must change structure of trustdb
#endif
typedef struct local_id_info *LOCAL_ID_INFO; typedef struct local_id_info *LOCAL_ID_INFO;
struct local_id_info { struct local_id_info {
LOCAL_ID_INFO next; 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 ); LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist );
static int list_sigs( ulong pubkey_id ); 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 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 /* a table used to keep track of ultimately trusted keys
* which are the ones from our secrings */ * which are the ones from our secrings */
@ -186,12 +189,11 @@ set_signature_packets_local_id( PKT_signature *sig )
if( rc) if( rc)
goto leave; goto leave;
if( !pk->local_id ) { if( !pk->local_id ) {
rc = tdbio_search_record( pk, &rec ); rc = tdbio_search_dir_record( pk, &rec );
if( rc == -1 ) if( rc == -1 )
rc = insert_trust_record( pk ); rc = insert_trust_record( pk );
if( rc ) if( rc )
goto leave; goto leave;
/* fixme: we should propagate the local_id to all copies of the PK */
} }
sig->local_id = pk->local_id; sig->local_id = pk->local_id;
@ -666,35 +668,36 @@ check_sigs( KBNODE keyblock, int *selfsig_okay, int *revoked )
* to the trustdb * to the trustdb
*/ */
static int static int
build_sigrecs( ulong pubkeyid ) build_sigrecs( ulong lid )
{ {
TRUSTREC rec, krec, rec2; TRUSTREC rec, krec, rec2;
KBNODE keyblock = NULL; KBNODE keyblock = NULL;
KBNODE node; KBNODE node;
int rc=0; int rc=0;
int i, selfsig, revoked; int i, selfsig, revoked;
ulong rnum, rnum2; ulong rnum, rnum2;
ulong first_sigrec = 0; ulong first_sigrec = 0;
if( DBG_TRUST ) 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 */ /* get the keyblock */
if( (rc=tdbio_read_record( pubkeyid, &rec, RECTYPE_DIR )) ) { if( (rc=tdbio_read_record( lid, &rec, RECTYPE_DIR )) ) {
log_error(_("%lu: build_sigrecs: can't read dir record\n"), pubkeyid ); log_error( "build_sigrecs: can't read dir record %lu\n"), lid );
goto leave; goto leave;
} }
if( (rc=tdbio_read_record( rec.r.dir.keyrec, &krec, RECTYPE_KEY )) ) { if( (rc=tdbio_read_record( rec.r.dir.keylist, &krec, RECTYPE_KEY )) ) {
log_error(_("%lu: build_sigrecs: can't read key record\n"), pubkeyid); log_error("build_sigrecs: can't read primary key record %lu\n"), lid);
goto leave; goto leave;
} }
rc = get_keyblock_byfprint( &keyblock, krec.r.key.fingerprint, rc = get_keyblock_byfprint( &keyblock, krec.r.key.fingerprint,
krec.r.key.fingerprint_len ); krec.r.key.fingerprint_len );
if( rc ) { if( rc ) {
log_error(_("build_sigrecs: get_keyblock_byfprint failed: %s\n"), log_error( "build_sigrecs: keyblock for %lu not found: %s\n",
g10_errstr(rc) ); lid, g10_errstr(rc) );
goto leave; goto leave;
} }
/* check all key signatures */ /* check all key signatures */
rc = check_sigs( keyblock, &selfsig, &revoked ); rc = check_sigs( keyblock, &selfsig, &revoked );
if( rc ) { if( rc ) {
@ -703,19 +706,18 @@ build_sigrecs( ulong pubkeyid )
} }
if( !selfsig ) { if( !selfsig ) {
log_error(_("build_sigrecs: self-signature missing\n") ); log_error(_("build_sigrecs: self-signature missing\n") );
update_no_sigs( pubkeyid, 2 ); tdbio_update_sigflag( lid, 2 );
rc = G10ERR_BAD_CERT; rc = G10ERR_BAD_CERT;
goto leave; goto leave;
} }
if( revoked ) { if( revoked ) {
log_info(_("build_sigrecs: key has been revoked\n") ); log_info(_("build_sigrecs: key has been revoked\n") );
update_no_sigs( pubkeyid, 3 ); tdbio_update_sigflag( lid, 3 );
} }
else 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 /* valid key signatures are now marked; we can now build the sigrecs */
* sigrecs */
memset( &rec, 0, sizeof rec ); memset( &rec, 0, sizeof rec );
rec.rectype = RECTYPE_SIG; rec.rectype = RECTYPE_SIG;
i = 0; i = 0;
@ -740,8 +742,8 @@ build_sigrecs( ulong pubkeyid )
/* write the record */ /* write the record */
rnum = tdbio_new_recnum(); rnum = tdbio_new_recnum();
if( rnum2 ) { /* write the stored record */ if( rnum2 ) { /* write the stored record */
rec2.r.sig.owner = pubkeyid; rec2.r.sig.lid = lid;
rec2.r.sig.chain = rnum; /* the next record number */ rec2.r.sig.next = rnum; /* the next record number */
rc = tdbio_write_record( rnum2, &rec2 ); rc = tdbio_write_record( rnum2, &rec2 );
if( rc ) { if( rc ) {
log_error(_("build_sigrecs: write_record failed\n") ); log_error(_("build_sigrecs: write_record failed\n") );
@ -756,7 +758,7 @@ build_sigrecs( ulong pubkeyid )
rec.rectype = RECTYPE_SIG; rec.rectype = RECTYPE_SIG;
i = 0; 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; rec.r.sig.sig[i].flag = 0;
i++; i++;
} }
@ -765,8 +767,8 @@ build_sigrecs( ulong pubkeyid )
/* write the record */ /* write the record */
rnum = tdbio_new_recnum(); rnum = tdbio_new_recnum();
if( rnum2 ) { /* write the stored record */ if( rnum2 ) { /* write the stored record */
rec2.r.sig.owner = pubkeyid; rec2.r.sig.lid = lid;
rec2.r.sig.chain = rnum; rec2.r.sig.next = rnum;
rc = tdbio_write_record( rnum2, &rec2 ); rc = tdbio_write_record( rnum2, &rec2 );
if( rc ) { if( rc ) {
log_error(_("build_sigrecs: write_record failed\n") ); log_error(_("build_sigrecs: write_record failed\n") );
@ -776,8 +778,8 @@ build_sigrecs( ulong pubkeyid )
first_sigrec = rnum2; first_sigrec = rnum2;
} }
if( i ) { /* write the pending record */ if( i ) { /* write the pending record */
rec.r.sig.owner = pubkeyid; rec.r.sig.lid = lid;
rec.r.sig.chain = 0; rec.r.sig.next = 0;
rc = tdbio_write_record( rnum, &rec ); rc = tdbio_write_record( rnum, &rec );
if( rc ) { if( rc ) {
log_error(_("build_sigrecs: write_record failed\n") ); log_error(_("build_sigrecs: write_record failed\n") );
@ -787,8 +789,7 @@ build_sigrecs( ulong pubkeyid )
first_sigrec = rnum; first_sigrec = rnum;
} }
} }
if( first_sigrec ) { if( first_sigrec ) { /* update the uid records */
/* update the dir record */
if( (rc =tdbio_read_record( pubkeyid, &rec, RECTYPE_DIR )) ) { if( (rc =tdbio_read_record( pubkeyid, &rec, RECTYPE_DIR )) ) {
log_error(_("update_dir_record: read failed\n")); log_error(_("update_dir_record: read failed\n"));
goto leave; goto leave;
@ -800,7 +801,7 @@ build_sigrecs( ulong pubkeyid )
} }
} }
else else
update_no_sigs( pubkeyid, revoked? 3:1 ); /* no signatures */ tdbio_update_sigflag( lid, revoked? 3:1 ); /* no signatures */
leave: leave:
release_kbnode( keyblock ); release_kbnode( keyblock );
@ -900,12 +901,24 @@ propagate_trust( TRUST_SEG_LIST tslist )
} }
/**************** /****************
* we have the pubkey record but nothing more is known. * check whether we already build signature records
* (function may re-read dr) * Return: true if we have.
*/ */
static int 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; int i, rc=0;
TRUST_SEG_LIST tsl, tsl2, tslist; TRUST_SEG_LIST tsl, tsl2, tslist;
@ -919,16 +932,27 @@ do_check( ulong pubkeyid, TRUSTREC *dr, unsigned *trustlevel )
*trustlevel = TRUST_UNDEFINED; *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 */ /* verify the cache */
/* do we have sigrecs */ /* do we have sigrecs */
if( !dr->r.dir.sigrec && !dr->r.dir.no_sigs) { if( !do_we_have_sigs( dr ) ) { /* no sigrecs, so build them */
/* no sigrecs, so build them */ rc = build_sigrecs( dr->lid );
rc = build_sigrecs( pubkeyid );
if( !rc ) /* and read again */ 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 ) if( dr->r.dir.no_sigs == 3 )
tflags |= TRUST_FLAG_REVOKED; tflags |= TRUST_FLAG_REVOKED;
@ -1199,9 +1223,7 @@ list_trust_path( int max_depth, const char *username )
* yes: return trustlevel from cache * yes: return trustlevel from cache
* no: make a cache record and all the other stuff * no: make a cache record and all the other stuff
* not found: * not found:
* Return with a trustlevel, saying that we do not have * try to insert the pubkey into the trustdb and check again
* a trust record for it. The caller may use insert_trust_record()
* and then call this function here again.
* *
* Problems: How do we get the complete keyblock to check that the * Problems: How do we get the complete keyblock to check that the
* cache record is actually valid? Think we need a clever * 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 */ /* get the pubkey record */
if( pk->local_id ) { if( pk->local_id ) {
if( tdbio_read_record( pk->local_id, &rec, RECTYPE_DIR ) ) { 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; return G10ERR_TRUSTDB;
} }
} }
else { /* no local_id: scan the trustdb */ else { /* no local_id: scan the trustdb */
if( (rc=tdbio_search_record( pk, &rec )) && rc != -1 ) { if( (rc=tdbio_search_dir_record( pk, &rec )) && rc != -1 ) {
log_error(_("check_trust: search_record failed: %s\n"), log_error("check_trust: search dir record failed: %s\n",
g10_errstr(rc)); g10_errstr(rc));
return rc; return rc;
} }
else if( rc == -1 ) { else if( rc == -1 ) { /* not found - insert */
rc = insert_trust_record( pk ); rc = insert_trust_record( pk );
if( rc ) { if( rc ) {
log_error(_("key %08lX: insert trust record failed: %s\n"), 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; trustlevel = TRUST_EXPIRED;
} }
else { else {
rc = do_check( pk->local_id, &rec, &trustlevel ); rc = do_check( &rec, &trustlevel );
if( rc ) { if( rc ) {
log_error(_("key %08lX.%lu: trust check failed: %s\n"), log_error(_("key %08lX.%lu: trust check failed: %s\n"),
keyid[1], pk->local_id, g10_errstr(rc)); 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. * This function fails if this record already exists.
*/ */
int 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]; u32 keyid[2];
ulong knum, dnum; ulong knum, dnum;
byte *fingerprint; byte *fingerprint;
size_t fingerlen; 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 ); log_bug("pk->local_id=%lu\n", (ulong)pk->local_id );
keyid_from_pk( pk, keyid ); fingerprint = fingerprint_from_pk( orig_pk, &fingerlen );
fingerprint = fingerprint_from_pk( 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(); knum = tdbio_new_recnum();
/* build dir record */ /* build dir record */
memset( &rec, 0, sizeof rec ); 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.keyid[1] = keyid[1];
rec.r.dir.keyrec = knum; rec.r.dir.keyrec = knum;
rec.r.dir.no_sigs = 0; 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 */ /* and the key record */
memset( &rec, 0, sizeof rec ); memset( &rec, 0, sizeof rec );
rec.rectype = RECTYPE_KEY; rec.rectype = RECTYPE_KEY;
@ -1469,8 +1582,14 @@ insert_trust_record( PKT_public_key *pk )
log_error("wrinting key record failed\n"); log_error("wrinting key record failed\n");
return G10ERR_TRUSTDB; 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 */ /* and store the LID */
pk->local_id = dnum; orig_pk->local_id = dnum;
return 0; 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; sl = NULL;
for(i=1 ; i < nfiles; i++ ) for(i=1 ; i < nfiles; i++ )
add_to_strlist( &sl, files[i] ); add_to_strlist( &sl, files[i] );
rc = proc_signature_packets( fp, sl ); rc = proc_signature_packets( fp, sl, sigfile );
free_strlist(sl); free_strlist(sl);
iobuf_close(fp); iobuf_close(fp);
return rc; 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) Fri Jun 26 11:44:24 1998 Werner Koch (wk@isil.d.shuttle.de)
* it.po: New file from Marco. * it.po: New file from Marco.

Binary file not shown.

View File

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