See ChangeLog: Wed Feb 10 17:15:39 CET 1999 Werner Koch

This commit is contained in:
Werner Koch 1999-02-10 16:22:40 +00:00
parent a16e15282a
commit 9a4f506a18
60 changed files with 2006 additions and 1340 deletions

View File

@ -1,3 +1,15 @@
Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* acinclude.m4 (GNUPG_CHECK_RDYNAMIC): Fix for freebsd 2.2
* configure.in: a lot of changes to allow selection of modules.
Add support for OS/2.
* acinclude.m4: add some more caching
* README: Spelling and grammar corrections (John A. Martin)
* INSTALL: Ditto.
Wed Jan 20 21:40:21 CET 1999 Werner Koch <wk@isil.d.shuttle.de> Wed Jan 20 21:40:21 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* configure.in: --enable-m-guard is now default * configure.in: --enable-m-guard is now default

44
INSTALL
View File

@ -13,10 +13,10 @@ Configure options for GNUPG
--disable-nls Disable NLS support (See ABOUT-NLS) --disable-nls Disable NLS support (See ABOUT-NLS)
--enable-m-debug Compile with the integrated malloc debugging stuff. --enable-m-debug Compile with the integrated malloc debugging stuff.
This makes the program slower but is checks every This makes the program slower but it checks every
free operation and can be used to create statistics free operation and can be used to create statistics
of memory usage. If this option is used the program of memory usage. If this option is used the program
option "--debug 32" displays every call to a a malloc option "--debug 32" displays every call to a malloc
function (this makes the program *really* slow), the function (this makes the program *really* slow), the
option "--debug 128" displays a memory statistic after option "--debug 128" displays a memory statistic after
the program run. the program run.
@ -55,8 +55,8 @@ Don't forget to delete "config.cache" and run "./config.status --recheck".
The Random Device The Random Device
================= =================
Random devices are available in Linux, FreeBSD and OpenBSD. Random devices are available in Linux, FreeBSD and OpenBSD.
The device files may not exist on your system, please check this The random device files may not exist on your system, please check whether
and create them if needed. they do and create them if needed.
The Linux files should look like this: The Linux files should look like this:
cr--r--r-- 1 root sys 1, 8 May 28 1997 /dev/random cr--r--r-- 1 root sys 1, 8 May 28 1997 /dev/random
@ -72,23 +72,23 @@ You can create them with:
mknod /dev/random c 2 3 mknod /dev/random c 2 3
mknod /dev/urandom c 2 4 mknod /dev/urandom c 2 4
Unices without a random devices must use another entropy collector Unices without a random devices must use another entropy collector. One
which is called rndunix and available as an extension module. You entropy collector called rndunix and available as an extension module. You
should put this in your ~/.gnupg/options file: should put this in your ~/.gnupg/options file:
===8<==================== ===8<====================
load-extension rndunix load-extension rndunix
===>8==================== ===>8====================
This collector works by running a lot of tools which yields more or This collector works by running a lot of commands that yield more or
less unpredictable output and feds this as entropy into the random less unpredictable output and feds this as entropy into the random
generator - It should work reliable but you should check whether generator - It should work reliably but you should check whether
it produces good output for your kind of Unix. There are some debug it produces good output for your version of Unix. There are some debug
options to help you (see cipher/rndunix.c). options to help you (see cipher/rndunix.c).
Installation Installation
============ ============
gpg is not installed as suid:root; if you want to do it, do it manually. gpg is not installed as suid:root; if you want to do that, do it manually.
We will use capabilities in the future. We will use capabilities in the future.
The ~/.gnupg directory will be created if it does not exist. Your first The ~/.gnupg directory will be created if it does not exist. Your first
@ -135,9 +135,9 @@ diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache' be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it. contains results you don't want to keep, you may remove or edit it.
The file `configure.in' is used to create `configure' by a program The file `configure.in' is used by the program `autoconf' to create
called `autoconf'. You only need `configure.in' if you want to change `configure'. You only need `configure.in' if you want to change it or
it or regenerate `configure' using a newer version of `autoconf'. regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is: The simplest way to compile this package is:
@ -147,7 +147,7 @@ The simplest way to compile this package is:
`sh ./configure' instead to prevent `csh' from trying to execute `sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself. `configure' itself.
Running `configure' takes awhile. While running, it prints some Running `configure' takes a while. While running, it prints some
messages telling which features it is checking for. messages telling which features it is checking for.
2. Type `make' to compile the package. 2. Type `make' to compile the package.
@ -177,19 +177,19 @@ a Bourne-compatible shell, you can do that on the command line like
this: this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
Or on systems that have the `env' program, you can do it like this: Or, on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures Compiling For Multiple Architectures
==================================== ====================================
You can compile the package for more than one kind of computer at the You can compile the package for more than one kind of computer at the same
same time, by placing the object files for each architecture in their time by placing the object files for each architecture in their own
own directory. To do this, you must use a version of `make' that directory. To do this, you must use a version of `make', such as GNU `make',
supports the `VPATH' variable, such as GNU `make'. `cd' to the that supports the `VPATH' variable. `cd' to the directory where you want the
directory where you want the object files and executables to go and run object files and executables to go and run the `configure' script.
the `configure' script. `configure' automatically checks for the `configure' automatically checks for the source code in the directory that
source code in the directory that `configure' is in and in `..'. `configure' is in and in `..'.
If you have to use a `make' that does not supports the `VPATH' If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time variable, you have to compile the package for one architecture at a time

View File

@ -10,7 +10,7 @@ all-recursive-am: g10defs.h
g10defs.h : config.h g10defs.h : config.h
@( set -e; \ @( set -e; \
echo "/* Generated automatically by Makefile */" ; \ echo "/* Generated automatically by Makefile */" ; \
echo "#ifdef __MINGW32__"; \ echo "#ifdef HAVE_DRIVE_LETTERS"; \
echo "#define G10_LOCALEDIR \"c:/lib/gnupg/locale\""; \ echo "#define G10_LOCALEDIR \"c:/lib/gnupg/locale\""; \
echo "#define GNUPG_LIBDIR \"c:/lib/gnupg\""; \ echo "#define GNUPG_LIBDIR \"c:/lib/gnupg\""; \
echo "#define GNUPG_DATADIR \"c:/lib/gnupg\""; \ echo "#define GNUPG_DATADIR \"c:/lib/gnupg\""; \

367
README
View File

@ -1,19 +1,19 @@
-----BEGIN PGP SIGNED MESSAGE----- -----BEGIN PGP SIGNED MESSAGE-----
GnuPG - The GNU Privacy Guard GnuPG - The GNU Privacy Guard
------------------------------- -------------------------------
Version 0.9 Version 0.9
GnuPG is now in Beta test and you should report all bugs to the GnuPG is now in Beta test and you should report all bugs to the
mailing list (see below). The 0.9.x versions are mainly released mailing list (see below). The 0.9.x versions are released mainly
to fix all remaining serious bugs. As soon as version 1.0 is out, to fix all remaining serious bugs. As soon as version 1.0 is out,
development will continue with a 1.1 series and bug fixes for the development will continue with a 1.1 series and bug fixes for the
1.0 version are released as needed. 1.0 version as needed.
GnuPG works best on GNU/Linux or *BSD. Other Unices are GnuPG works best on GNU/Linux or *BSD. Other Unices are
also supported but not as good tested as those Freenix ones. also supported but are not as well tested as the Free Unices.
Please verify the tar file; there is a PGP2 and a GnuPG/PGP5 Please verify the tar file with the PGP2 or GnuPG/PGP5
signature available. My PGP2 key is well known and published in signatures provided. My PGP2 key is well known and published in
the "Global Trust Register for 1998", ISBN 0-9532397-0-5. the "Global Trust Register for 1998", ISBN 0-9532397-0-5.
I have included my pubring as "g10/pubring.asc", which contains I have included my pubring as "g10/pubring.asc", which contains
@ -25,33 +25,33 @@
"pub 1024D/621CC013 1998-07-07 Werner Koch <werner.koch@guug.de>" "pub 1024D/621CC013 1998-07-07 Werner Koch <werner.koch@guug.de>"
"Key fingerprint = ECAF 7590 EB34 43B5 C7CF 3ACB 6C7E E1B8 621C C013" "Key fingerprint = ECAF 7590 EB34 43B5 C7CF 3ACB 6C7E E1B8 621C C013"
You may want add it to your GnuPG pubring and use it in the future to You may want add my new DSA key to your GnuPG pubring and use it in
verify new releases. Because you verified this README file and the future to verify new releases. Because you verified this README
_checked_that_it_is_really_my PGP2 key 0C9857A5, you can be sure file and _checked_that_it_is_really_my PGP2 key 0C9857A5, you can be
that the above fingerprints are correct. sure that the above fingerprints are correct.
Please subscribe to g10@net.lut.ac.uk by sending a mail with Please subscribe to g10@net.lut.ac.uk by sending a mail with
the word "subscribe" in the body to "g10-request@net.lut.ac.uk". the word "subscribe" in the body to "g10-request@net.lut.ac.uk".
This mailing list is a closed one (only subscribers are allowed This mailing list is closed (only subscribers are allowed to post)
to post) to avoid misuse by folks who don't know the Netiquette to avoid misuse by folks who don't know the Netiquette and trash
and trash your mailspool with commercial junk. your mailspool with commercial junk.
See the file COPYING for copyright and warranty information. See the file COPYING for copyright and warranty information.
GnuPG is in compliance with RFC2440 (OpenPGP), see doc/OpenPGP for GnuPG is in compliance with RFC2440 (OpenPGP), see doc/OpenPGP for
details. details.
Due to the fact that GnuPG does not use use any patented algorithm, Because GnuPG does not use use any patented algorithm it cannot be
it cannot be compatible with PGP2 versions; PGP 2.x does only use compatible with PGP2 versions. PGP 2.x uses only IDEA (which is
IDEA (which is patented worldwide) and RSA (which is patented in patented worldwide) and RSA (which is patented in the United States
the United States until Sep 20, 2000). until Sep 20, 2000).
The default algorithms are now DSA and ElGamal. ElGamal for signing The default algorithms are now DSA and ElGamal. ElGamal for signing
is still available, but due to the larger size of such signatures it is still available, but because of the larger size of such
is depreciated (Please note that the GnuPG implementation of ElGamal signatures it is deprecated (Please note that the GnuPG
signatures is *not* insecure). Symmetric algorithms are: 3DES, implementation of ElGamal signatures is *not* insecure). Symmetric
Blowfish and CAST5 (Twofish will come soon), available digest algorithms are: 3DES, Blowfish, and CAST5 (Twofish will come soon).
algorithms are MD5, RIPEMD160, SHA1 and TIGER/192. Digest algorithms available are MD5, RIPEMD160, SHA1, and TIGER/192.
Installation Installation
@ -61,7 +61,7 @@
Here is a quick summary: Here is a quick summary:
1) "./configure" 1) "./configure"
2) "make" 2) "make"
@ -69,24 +69,25 @@
4) You end up with the binaries "gpg" and "gpgm" in /usr/local/bin. 4) You end up with the binaries "gpg" and "gpgm" in /usr/local/bin.
5) Optional, but suggested: install the binary "gpg" as suid root. 5) Optional, but suggested, install the binary "gpg" as suid root.
Intro Introduction
----- ------------
This is a brief overview how to use GnuPG - it is highly suggested
that you read the manual^H^H^H more information about the use This is a brief overview how to use GnuPG - it is strongly suggested
of cryptography. GnuPG is only the technical tool to do it and that you read the manual^H^H^H more information about the use of
the security highly depends on that YOU KNOW WHAT YOU ARE DOING. cryptography. GnuPG is only a tool, secure results require that YOU
KNOW WHAT YOU ARE DOING.
If you already have a DSA key from PGP 5 (they call them DH/ElGamal) If you already have a DSA key from PGP 5 (they call them DH/ElGamal)
you can simply copy the pgp keyrings over the GnuPG keyrings after you can simply copy the pgp keyrings over the GnuPG keyrings after
running gpg once, so that it can create the correct directory. running gpg once to create the correct directory.
The normal way to create a key is: The normal way to create a key is
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 the key parameters, GnuPG needs to gather good random numbers for the key parameters, GnuPG needs to gather
@ -98,209 +99,212 @@
access - don't do it over the network or on a machine used also access - don't do it over the network or on a machine used also
by others - especially if you have no access to the root account. by others - especially if you have no access to the root account.
When you are asked for a passphrase; use a good one which you can easy When you are asked for a passphrase use a good one which you can
remember. Don't make the passphrase too long because you have to easy remember. Don't make the passphrase too long because you have
type it for every decryption or signing; but - AND THIS IS VERY to type it for every decryption or signing; but, - AND THIS IS VERY
IMPORTANT - use a good one which is not easily guessable as the IMPORTANT - use a good one that is not easily to guess because the
security of the whole system relies on your secret key and the security of the whole system relies on your secret key and the
passphrase is used to protect this secret key in case someone was passphrase that protects it when someone gains access to your secret
able to get access to your secret keyring. A good way to select keyring. A good way to select a passphrase is to figure out a short
a passphrase is to figure out a short nonsense sentence which makes nonsense sentence which makes some sense for you and modify it by
some sense for you and modify it by inserting extra spaces, non-letters inserting extra spaces, non-letters and changing the case of some
and changing the case of some characters - this is really easy to characters - this is really easy to remember especially if you
remember especially if you associate some pictures with it. associate some pictures with it.
Then you should create a revocation certificate in case someone Next, you should create a revocation certificate in case someone
gets knowledge of your secret key or you forgot your passphrase: 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, Run this command and store the revocation certificate away. The output
so that you can print it and (hopefully never) re-create it if is always ASCII armored, so that you can print it and (hopefully
your electronic media fails. never) re-create it if your electronic media fails.
Now you can use your key to create digital signatures: Now you can use your key to create digital signatures
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
attached. signature attached.
gpg -sa file gpg -sa file
Same as above, but creates the file.asc which is ascii armored and Same as above, but creates a file "file.asc" which is ASCII armored
and ready for sending by mail. Note: It is better to use your and and ready for sending by mail. It is better to use your
mailers features to create signatures (The mailer uses GnuPG to do mailers features to create signatures (The mailer uses GnuPG to do
this) because the mailer has the ability to MIME encode such this) because the mailer has the ability to MIME encode such
signatures - but this is not a security issue. signatures - but this is not a security issue.
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".
Everyone who knows your public key (you can and should publish Everyone who knows your public key (you can and should publish
your key by putting it on a key server, a web page or in your .plan your key by putting it on a key server, a web page or in your .plan
file) is now able to check whether you really signed this text; file) is now able to check whether you really signed this text
gpg --verify file gpg --verify file
GnuPG now checks whether the signature is valid and prints an GnuPG now checks whether the signature is valid and prints an
appropriate message. If the signature is good, you know at least appropriate message. If the signature is good, you know at least
that the person (or machine) has access to the secret key which that the person (or machine) has access to the secret key which
corresponds to the published public key. corresponds to the published public key.
If you run gpg without an option it will verify the signature and If you run gpg without an option it will verify the signature and
create a new file which is identical to the original file. gpg create a new file that is identical to the original. gpg can also
can also run as a filter, so that you can pipe data to verify run as a filter, so that you can pipe data to verify trough it
trough it:
cat signed-file | gpg | wc -l cat signed-file | gpg | wc -l
will check the signature of signed-file and then display the which will check the signature of signed-file and then display the
number of lines in the original file. number of lines in the original file.
To send a message encrypted to someone you can use this: To send a message encrypted to someone you can use
gpg -e -r heine file gpg -e -r heine file
This encrypts file with the public key of the user "heine" and This encrypts "file" with the public key of the user "heine" and
writes it to "file.gpg" writes it to "file.gpg"
echo "hallo" | gpg -ea -r heine | mail heine echo "hello" | gpg -ea -r heine | mail heine
Ditto, but encrypts "hallo\n" and mails it as ascii armored message Ditto, but encrypts "hello\n" and mails it as ASCII armored message
to the user with the mail address heine. to the user with the mail address heine.
gpg -se -r heine file gpg -se -r heine file
This encrypts file with the public key of "heine" and writes it This encrypts "file" with the public key of "heine" and writes it
to "file.gpg" after signing it with your user id. to "file.gpg" after signing it with your user id.
gpg -se -r heine -u Suttner file gpg -se -r heine -u Suttner file
Ditto, but sign the file with your alternative user id "Suttner" Ditto, but sign the file with your alternative user id "Suttner"
GnuPG has some options to help you publish public keys; this is GnuPG has some options to help you publish public keys. This is
called "exporting" a key: called "exporting" a key, thus
gpg --export >all-my-keys gpg --export >all-my-keys
exports all the keys in the keyring and writes them (in a binary format) exports all the keys in the keyring and writes them (in a binary
to all-my-keys. You may then mail "all-my-keys" as an MIME attachment format) to "all-my-keys". You may then mail "all-my-keys" as an
to someone else or put it on an FTP server. To export only some MIME attachment to someone else or put it on an FTP server. To
user IDs, you give them as arguments on the command line. export only some user IDs, you give them as arguments on the command
line.
To mail a public key or put it on a web page you have to create To mail a public key or put it on a web page you have to create
the key in ASCII armored format: the key in ASCII armored format
gpg --export --armor | mail panther@tiger.int gpg --export --armor | mail panther@tiger.int
This will send all your public keys to your friend panther. This will send all your public keys to your friend panther.
If you have received a key from someone else you can put it If you have received a key from someone else you can put it
into your public keyring; is called "importing": into your public keyring. This is called "importing"
gpg --import [filenames] gpg --import [filenames]
New keys are appended to your keyring and already existing New keys are appended to your keyring and already existing
keys are updated. Note that GnuPG does not allow keys which keys are updated. Note that GnuPG does not import keys that
are not self-signed by the user. are not self-signed.
Because anyone can claim that the public key belongs to her Because anyone can claim that a public key belongs to her
we must have some way to check that the public key really belongs we must have some way to check that a public key really belongs
to the owner. This can be achieved by comparing the key during to the owner. This can be achieved by comparing the key during
a phone call. Sure, it is not very easy to compare a binary file a phone call. Sure, it is not very easy to compare a binary file
by reading the complete hex dump of the file - GnuPG (and nearly by reading the complete hex dump of the file - GnuPG (and nearly
every other program used for management of cryptographic keys) every other program used for management of cryptographic keys)
provides other solutions: provides other solutions.
gpg --fingerprint <username> gpg --fingerprint <username>
prints the so called "fingerprint" of the given username; this prints the so called "fingerprint" of the given username which
is a sequence of hex bytes (which you may have noticed in mail is a sequence of hex bytes (which you may have noticed in mail
sigs or on business cards) which uniquely identify the public sigs or on business cards) that uniquely identifies the public
key - two different keys will always have different fingerprints. key - different keys will always have different fingerprints.
It is easy to compare this fingerprint by phone and I suggest It is easy to compare fingerprints by phone and I suggest
that you print your fingerprint on the back of your business that you print your fingerprint on the back of your business
card. card.
If you don't know the owner of the public key you are in trouble; If you don't know the owner of the public key you are in trouble.
but wait: A friend of you knows someone who knows someone who Suppose however that friend of yours knows someone who knows someone
has met the owner of the public key at some computer conference. who has met the owner of the public key at some computer conference.
So all the persons between you and the public key holder may now Suppose that all the people between you and the public key holder
act as introducer to you; this is done by signing the keys and may now act as introducers to you. Introducers signing keys thereby
thereby certifying the other keys. If you then trust all the certify that they know the owner of the keys they sign. If you then
introducers to correctly sign other keys, you can be be sure that trust all the introducers to have correctly signed other keys, you
the other key really belongs to the one who claims so. can be be sure that the other key really belongs to the one who
claims to own it..
There are 2 steps to validate a target key: There are 2 steps to validate a key:
1. First check that there is a complete chain 1. First check that there is a complete chain
of signed keys from the public key you want to use of signed keys from the public key you want to use
and your key and verify each signature. and your key and verify each signature.
2. Make sure that you have full trust in the certificates 2. Make sure that you have full trust in the certificates
of all the introduces between the public key holder and of all the introduces between the public key holder and
you. you.
Step 2 is the more complicated part because there is no easy way Step 2 is the more complicated part because there is no easy way
for a computer to decide who is trustworthy and who is not. GnuPG for a computer to decide who is trustworthy and who is not. GnuPG
leaves this decision to you and will ask you for a trust value leaves this decision to you and will ask you for a trust value
(here also referenced as the owner-trust of a key) for every key (here also referenced as the owner-trust of a key) for every key
needed to check the chain of certificates. You may choose from: needed to check the chain of certificates. You may choose from:
a) "I don't know" - then it is not possible to use any a) "I don't know" - then it is not possible to use any
of the chains of certificates, in which this key is used of the chains of certificates, in which this key is used
as an introducer, to validate the target key. Use this if as an introducer, to validate the target key. Use this if
you don't know the introducer. you don't know the introducer.
b) "I do not trust" - Use this if you know that the introducer b) "I do not trust" - Use this if you know that the introducer
does not do a good job in certifying other keys. The effect does not do a good job in certifying other keys. The effect
is the same as with a) but for a) you may later want to is the same as with a) but for a) you may later want to
change the value because you got new information about this change the value because you got new information about this
introducer. introducer.
c) "I trust marginally" - Use this if you assume that the c) "I trust marginally" - Use this if you assume that the
introducer knows what he is doing. Together with some introducer knows what he is doing. Together with some
other marginally trusted keys, GnuPG validates the target other marginally trusted keys, GnuPG validates the target
key then as good. key then as good.
d) "I fully trust" - Use this if you really know that this d) "I fully trust" - Use this if you really know that this
introducer does a good job when certifying other keys. introducer does a good job when certifying other keys.
If all the introducer are of this trust value, GnuPG If all the introducer are of this trust value, GnuPG
normally needs only one chain of signatures to validate normally needs only one chain of signatures to validate
a target key okay. (But this may be adjusted with the help a target key okay. (But this may be adjusted with the help
of some options). of some options).
These information are confidential because they give your This information is confidential because it gives your personal
personal opinion on the trustworthy of someone else. Therefore opinion on the trustworthiness of someone else. Therefore this data
this data is not stored in the keyring but in the "trustdb" is not stored in the keyring but in the "trustdb"
(~/.gnupg/trustdb.gpg). Do not assign a high trust value just (~/.gnupg/trustdb.gpg). Do not assign a high trust value just
because the introducer is a friend of you - decide how far she because the introducer is a friend of yours - decide how well she
understands all the implications of key signatures and you may understands the implications of key signatures and you may want to
want to tell him more about public key cryptography so you tell her more about public key cryptography so you can later change
can later change the trust value you assigned. the trust value you assigned.
Okay, here is how GnuPG helps you in key management: Most stuff is Okay, here is how GnuPG helps you with key management. Most stuff
done with the --edit-key command: is done with the --edit-key command
gpg --edit-key <keyid or username> gpg --edit-key <keyid or username>
GnuPG displays some information about the key and then prompts GnuPG displays some information about the key and then prompts
for a command (enter "help" to see a list of commands and see for a command (enter "help" to see a list of commands and see
the man page for a more detailed explanation). To sign a key the man page for a more detailed explanation). To sign a key
you select the user ID you want to sign by entering the number you select the user ID you want to sign by entering the number
which is displayed in the leftmost column (or do nothing if the that is displayed in the leftmost column (or do nothing if the
key has only one user ID) and then enter the command "sign" and key has only one user ID) and then enter the command "sign" and
follow all the prompts. When you are ready, give the command follow all the prompts. When you are ready, give the command
"save" (or use "quit" to cancel your actions). "save" (or use "quit" to cancel your actions).
If you want to sign the key with another user ID of yours, you If you want to sign the key with another of your user IDs, you
must give an "-u" option on the command line together with the must give an "-u" option on the command line together with the
"--edit-key". "--edit-key".
Normally you want to sign only one user ID because GnuPG Normally you want to sign only one user ID because GnuPG
does only use one and this keeps the public key certificate uses only one and this keeps the public key certificate
small. Because such key signatures are very important you small. Because such key signatures are very important you
should make sure that the signators of your key sign a user ID should make sure that the signatories of your key sign a user ID
which is very likely to stay for a long time - choose one with an which is very likely to stay for a long time - choose one with an
email address you have full control of or do not enter an email email address you have full control of or do not enter an email
address at all. In future GnuPG will have a way to tell which address at all. In future GnuPG will have a way to tell which
user ID is the one with an email address you prefer - because user ID is the one with an email address you prefer - because
you have no signatures on this email address it is easy to change you have no signatures on this email address it is easy to change
this address. Remember: Your signators sign your public key (the this address. Remember, your signatories sign your public key (the
primary one) together with one of your user IDs - so it is not possible primary one) together with one of your user IDs - so it is not possible
to change the user ID later without voiding all the signatures. to change the user ID later without voiding all the signatures.
@ -310,51 +314,59 @@
trust you assign to a key). trust you assign to a key).
7 Ways to Specify a User ID 8 Ways to Specify a User ID
-------------------------- --------------------------
There are several ways to specify a user ID, here are some examples: There are several ways to specify a user ID, here are some examples.
* 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: * By an exact string:
"=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>"
* By word match
"+Heinrich Heine duesseldorf"
All words must match excatly (not case sensitive) and appear in
any order in the user ID. Words are any sequences of letters,
digits, the underscore and characters with bit 7 set.
* By the Local ID (from the trust DB): * By the Local ID (from the trust DB):
"#34" "#34"
This may be used by a MUA to specify an exact key after selecting This may 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 using a special option or an extra utility)
* Or by the usual substring: * Or by the usual substring:
"Heine" "Heine"
"*Heine" "*Heine"
The '*' indicates substring search explicitly. The '*' indicates substring search explicitly.
@ -363,7 +375,7 @@
---------- ----------
If you use the option "--batch", GnuPG runs in non-interactive mode and If you use the option "--batch", GnuPG runs in non-interactive mode and
never prompts for input data. This does not even allow entering the never prompts for input data. This does not even allow entering the
passphrase; until we have a better solution (something like ssh-agent), passphrase. Until we have a better solution (something like ssh-agent),
you can use the option "--passphrase-fd n", which works like PGPs you can use the option "--passphrase-fd n", which works like PGPs
PGPPASSFD. PGPPASSFD.
@ -375,29 +387,29 @@
----------- -----------
GnuPG returns with an exit status of 1 if in batch mode and a bad signature GnuPG returns with an exit status of 1 if in batch mode and a bad signature
has been detected or 2 or higher for all other errors. You should parse has been detected or 2 or higher for all other errors. You should parse
stderr or better the output of the fd specified with --status-fd to get stderr or, better, the output of the fd specified with --status-fd to get
detailed information about the errors. detailed information about the errors.
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. This command should be able inner structure of a encrypted packet. This command should list all
to list all kinds of rfc2440 messages. kinds of rfc2440 messages.
gpgm --list-trustdb gpgm --list-trustdb
List the contents of the trust DB in a human readable format List the contents of the trust DB 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 username gpgm --list-trust-path username
List the possible trust paths for the given username. The length List the possible trust paths for the given username. The length
of such a trust path is limited by the option --max-cert-depth of such a trust path is limited by the option --max-cert-depth
@ -415,22 +427,21 @@
See http://www.gnupg.org/mirrors.html for a list of FTP mirrors See http://www.gnupg.org/mirrors.html for a list of FTP mirrors
and use them if possible. and use them if possible.
Please direct bug reports to <gnupg-bugs@gnu.org> or better Please direct bug reports to <gnupg-bugs@gnu.org> or, better,
post them to the mailing list <g10@net.lut.ac.uk> (this is a post them to the mailing list <g10@net.lut.ac.uk> (this is a
closed list - subscribe before posting, see above (~line 33)). closed list - subscribe before posting, see above (~line 33)).
Please direct questions about GnuPG to the mailing list or Please direct questions about GnuPG to the mailing list or
one of the pgp newsgroups; this gives me more time to improve one of the pgp newsgroups and give me more time to improve
GnuPG. Commercial support for GnuPG will be available soon. GnuPG. Commercial support for GnuPG will be available soon.
Have fun and remember: Echelon is looking at you kid. Have fun and remember: Echelon is looking at you kid.
-----BEGIN PGP SIGNATURE----- -----BEGIN PGP SIGNATURE-----
Version: GnuPG v0.9.1 (GNU/Linux) Version: GnuPG v0.9.2 (GNU/Linux)
Comment: For info see http://www.gnupg.org Comment: For info see http://www.gnupg.org
iQB1AwUBNpyIDR0Z9MEMmFelAQGn4gL+IVlEye5I6LplxdUExsrHQpLV21H0UXFa iQB1AwUBNr2fPh0Z9MEMmFelAQHqNAL/e7pApR0CGUJ/zuIsjaVhNGPEgKAglcEd
/Dl1T/HjrGHj41NeW2evO4Ck2K6Z0TG5jPg9CuJdcJp0siJ8odO7BTLaF3r6gwxF YuVdB+RCN0wq7ZfI0AHU2FdVISRACmSN3xituTTgeiOUsczM40EZ4l1XNfyRF768
CA4EXgqhSyE8PXRPS4m4M5I7Ru/bsZrF fglui6XxEeYHFY7mSQMgzzFWDG0Squx0
=HfE0 =enRo
-----END PGP SIGNATURE----- -----END PGP SIGNATURE-----

9
TODO
View File

@ -8,8 +8,13 @@ Bugs
* clearsign bug Greg Troxel Jan 11. * clearsign bug Greg Troxel Jan 11.
* README does not verify okay. verify inserts an extra CR,LF
just before "Esoteric Command" (after ~8k of text).
Important Important
---------- ----------
* replace gettext by a non exploitable one.
* Check revocation and expire stuff. PLEASE: THIS MUST BE TESTED! * Check revocation and expire stuff. PLEASE: THIS MUST BE TESTED!
* Check calculation of key validity. PLEASE: IT IS IMPORTED THAT * Check calculation of key validity. PLEASE: IT IS IMPORTED THAT
@ -34,6 +39,8 @@ Needed
-Wl,-export-dynamic flag from my Makefile and it linked and seems to -Wl,-export-dynamic flag from my Makefile and it linked and seems to
be working OK so far. be working OK so far.
* Use capabilities if available.
Minor Bugs Minor Bugs
---------- ----------
@ -56,7 +63,7 @@ Nice to have
really make sense? really make sense?
* change the fake_data stuff to mpi_set_opaque * change the fake_data stuff to mpi_set_opaque
* How about letting something like 'gpg --version -v', list the * How about letting something like 'gpg --version -v', list the
effective options. effective options. Too much work.
* Stats about used random numbers. * Stats about used random numbers.

View File

@ -32,6 +32,7 @@
#undef VERSION #undef VERSION
#undef PACKAGE #undef PACKAGE
#undef PRINTABLE_OS_NAME #undef PRINTABLE_OS_NAME
#undef IS_DEVELOPMENT_VERSION
/* Define if your locale.h file contains LC_MESSAGES. */ /* Define if your locale.h file contains LC_MESSAGES. */
#undef HAVE_LC_MESSAGES #undef HAVE_LC_MESSAGES
@ -64,14 +65,6 @@
#undef HAVE_BROKEN_MLOCK #undef HAVE_BROKEN_MLOCK
/* One of the following macros is defined to select which of
* the cipher/rndxxxx.c is linked into the program */
#undef USE_RNDLINUX
#undef USE_RNDUNIX
#undef USE_RNDOS2
#undef USE_RNDATARI
#undef USE_RNDW32
#undef USE_RNDMVS
/* defined if we have a /dev/random and /dev/urandom */ /* defined if we have a /dev/random and /dev/urandom */
#undef HAVE_DEV_RANDOM #undef HAVE_DEV_RANDOM
/* and the real names of the random devices */ /* and the real names of the random devices */
@ -92,6 +85,11 @@
#undef USE_ONLY_8DOT3 #undef USE_ONLY_8DOT3
/* defined if we must run on a stupid file system */ /* defined if we must run on a stupid file system */
#undef HAVE_DRIVE_LETTERS #undef HAVE_DRIVE_LETTERS
/* defined if we run on some of the PCDOS like systems (DOS, Windoze. OS/2)
* with special properties like no file modes */
#undef HAVE_DOSISH_SYSTEM
@BOTTOM@ @BOTTOM@

View File

@ -1,4 +1,4 @@
dnl macros to configure g10 dnl macros to configure g10 7cache_va
dnl GNUPG_MSG_PRINT(STRING) dnl GNUPG_MSG_PRINT(STRING)
@ -203,6 +203,9 @@ define(GNUPG_CHECK_RDYNAMIC,
solaris*) solaris*)
CFLAGS_RDYNAMIC="-Wl,-dy" CFLAGS_RDYNAMIC="-Wl,-dy"
;; ;;
freebsd2*)
CFLAGS_RDYNAMIC=""
;;
*) *)
CFLAGS_RDYNAMIC="-Wl,-export-dynamic" CFLAGS_RDYNAMIC="-Wl,-export-dynamic"
;; ;;
@ -221,8 +224,9 @@ dnl
define(GNUPG_CHECK_IPC, define(GNUPG_CHECK_IPC,
[ AC_CHECK_HEADERS(sys/ipc.h sys/shm.h) [ AC_CHECK_HEADERS(sys/ipc.h sys/shm.h)
if test "$ac_cv_header_sys_shm_h" = "yes"; then if test "$ac_cv_header_sys_shm_h" = "yes"; then
AC_MSG_CHECKING(whether shmctl IPC_RMID allowes subsequent attaches) AC_MSG_CHECKING(whether IPC_RMID allowes subsequent attaches)
AC_TRY_RUN([ AC_CACHE_VAL(gnupg_cv_ipc_rmid_deferred_release,
AC_TRY_RUN([
#include <sys/types.h> #include <sys/types.h>
#include <sys/ipc.h> #include <sys/ipc.h>
#include <sys/shm.h> #include <sys/shm.h>
@ -245,19 +249,38 @@ define(GNUPG_CHECK_IPC,
exit (0); exit (0);
} }
], ],
AC_DEFINE(IPC_RMID_DEFERRED_RELEASE) gnupg_cv_ipc_rmid_deferred_release="yes",
AC_MSG_RESULT(yes), gnupg_cv_ipc_rmid_deferred_release="no",
AC_MSG_RESULT(no), gnupg_cv_ipc_rmid_deferred_release="assume-no")
AC_MSG_RESULT(assuming no)) )
if test "$gnupg_cv_ipc_rmid_deferred_release" = "yes"; then
AC_DEFINE(IPC_RMID_DEFERRED_RELEASE)
AC_MSG_RESULT(yes)
else
if test "$gnupg_cv_ipc_rmid_deferred_release" = "no"; then
AC_MSG_RESULT(no)
else
AC_MSG_RESULT([assuming no])
fi
fi
AC_MSG_CHECKING(whether SHM_LOCK is available) AC_MSG_CHECKING(whether SHM_LOCK is available)
AC_TRY_COMPILE([#include <sys/types.h> AC_CACHE_VAL(gnupg_cv_ipc_have_shm_lock,
AC_TRY_COMPILE([#include <sys/types.h>
#include <sys/ipc.h> #include <sys/ipc.h>
#include <sys/shm.h>],[ #include <sys/shm.h>],[
int foo( int shm_id ) { shmctl(shm_id, SHM_LOCK, 0); } int foo( int shm_id ) { shmctl(shm_id, SHM_LOCK, 0); }
], ],
gnupg_cv_ipc_have_shm_lock="yes",
gnupg_cv_ipc_have_shm_lock="no"
)
)
if test "$gnupg_cv_ipc_have_shm_lock" = "yes"; then
AC_DEFINE(IPC_HAVE_SHM_LOCK) AC_DEFINE(IPC_HAVE_SHM_LOCK)
AC_MSG_RESULT(yes), AC_MSG_RESULT(yes)
AC_MSG_RESULT(no)) else
AC_MSG_RESULT(no)
fi
fi fi
]) ])
@ -272,7 +295,8 @@ define(GNUPG_CHECK_MLOCK,
[ AC_CHECK_FUNCS(mlock) [ AC_CHECK_FUNCS(mlock)
if test "$ac_cv_func_mlock" = "yes"; then if test "$ac_cv_func_mlock" = "yes"; then
AC_MSG_CHECKING(whether mlock is broken) AC_MSG_CHECKING(whether mlock is broken)
AC_TRY_RUN([ AC_CACHE_VAL(gnupg_cv_have_broken_mlock,
AC_TRY_RUN([
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
@ -299,10 +323,21 @@ define(GNUPG_CHECK_MLOCK,
} }
], ],
AC_MSG_RESULT(no), gnupg_cv_have_broken_mlock="no",
AC_DEFINE(HAVE_BROKEN_MLOCK) gnupg_cv_have_broken_mlock="yes",
AC_MSG_RESULT(yes), gnupg_cv_have_broken_mlock="assume-no"
AC_MSG_RESULT(assuming no)) )
)
if test "$gnupg_cv_have_broken_mlock" = "yes"; then
AC_DEFINE(HAVE_BROKEN_MLOCK)
AC_MSG_RESULT(yes)
else
if test "$gnupg_cv_have_broken_mlock" = "no"; then
AC_MSG_RESULT(no)
else
AC_MSG_RESULT(assuming no)
fi
fi
fi fi
]) ])

View File

@ -1,3 +1,15 @@
Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* Makefile.am: Modules are now figured out by configure
* construct.c: New. Generated by configure. Changed all modules
to work with that.
* sha1.h: Removed.
* md5.h: Removed.
* twofish.c: Changed interface to allow Twofish/256
* rndunix.c (start_gatherer): Die on SIGPIPE.
Wed Jan 20 18:59:49 CET 1999 Werner Koch <wk@isil.d.shuttle.de> Wed Jan 20 18:59:49 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* rndunix.c (gather_random): Fix to avoid infinite loop. * rndunix.c (gather_random): Fix to avoid infinite loop.

View File

@ -1,12 +1,33 @@
## Process this file with automake to produce Makefile.in ## Process this file with automake to produce Makefile.in
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl
noinst_LIBRARIES = libcipher.a noinst_LIBRARIES = libcipher.a
EXTRA_PROGRAMS = tiger twofish rndunix rndlinux # The configure script greps the module names from the following lines.
# You must also add all these names to EXTRA_PROGRAMS some lines below
# and EXTRA_foo_SOURCES entries.
# Hmmm is there a more easy way to do this? (EXTRA_PROGRAMS
# might also list programs which are not modules)
# MODULES: rndunix rndlinux
# MODULES: sha1 rmd160 md5 tiger
# MODULES: twofish
EXTRA_PROGRAMS = rndunix rndlinux \
sha1 rmd160 md5 tiger \
twofish
EXTRA_rndlinux_SOURCES = rndlinux.c
EXTRA_rndunix_SOURCES = rndunix.c
EXTRA_md5_SOURCES = md5.c
EXTRA_rmd160_SOURCES = rmd160.c
EXTRA_sha1_SOURCES = sha1.c
EXTRA_tiger_SOURCES = tiger.c
EXTRA_twofish_SOURCES = twofish.c
if ENABLE_GNUPG_EXTENSIONS if ENABLE_GNUPG_EXTENSIONS
pkglib_PROGRAMS = @DYNAMIC_CIPHER_MODS@ @DYNAMIC_RANDOM_MODS@ pkglib_PROGRAMS = @DYNAMIC_CIPHER_MODS@
else else
pkglib_PROGRAMS = pkglib_PROGRAMS =
endif endif
@ -27,37 +48,41 @@ libcipher_a_SOURCES = cipher.c \
cast5.h \ cast5.h \
elgamal.c \ elgamal.c \
elgamal.h \ elgamal.h \
md5.c \
md5.h \
primegen.c \ primegen.c \
random.h \ random.h \
random.c \ random.c \
rand-internal.h \ rand-internal.h \
rmd.h \ rmd.h \
rmd160.c \
sha1.h \
sha1.c \
dsa.h \ dsa.h \
dsa.c \ dsa.c \
g10c.c \ g10c.c \
smallprime.c smallprime.c \
construct.c
# configure creates the constructor file
BUILT_SOURCES = construct.c
EXTRA_libcipher_a_SOURCES = rndlinux.c rndunix.c libcipher_a_DEPENDENCIES = @STATIC_CIPHER_OBJS@
EXTRA_tiger_SOURCES = tiger.c libcipher_a_LIBADD = @STATIC_CIPHER_OBJS@
EXTRA_twofish_SOURCES = twofish.c
libcipher_a_DEPENDENCIES = @STATIC_RANDOM_OBJS@ @STATIC_CIPHER_OBJS@
libcipher_a_LIBADD = @STATIC_RANDOM_OBJS@ @STATIC_CIPHER_OBJS@
# If I remember it correct, automake 1.4 has a feature to set
# fooFLAGS depending on the program. So we should check it out.
tiger: $(srcdir)/tiger.c tiger: $(srcdir)/tiger.c
`echo $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o tiger $(srcdir)/tiger.c | \ `echo $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o tiger $(srcdir)/tiger.c | \
sed -e 's/-O[2-9]*/-O1/' ` sed -e 's/-O[2-9]*/-O1/g' `
tiger.o: $(srcdir)/tiger.c
`echo $(COMPILE) $(srcdir)/tiger.c | sed -e 's/-O[2-9]*/-O1/g' `
twofish: $(srcdir)/twofish.c twofish: $(srcdir)/twofish.c
`echo $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o twofish $(srcdir)/twofish.c | \ `echo $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o twofish $(srcdir)/twofish.c | \
sed -e 's/-O[0-9]*/ /' ` sed -e 's/-O[0-9]*/ /g' `
twofish.o: $(srcdir)/twofish.c
`echo $(COMPILE) $(srcdir)/twofish.c | sed -e 's/-O[0-9]*/ /g' `
rndunix: $(srcdir)/rndunix.c rndunix: $(srcdir)/rndunix.c

View File

@ -37,6 +37,7 @@
#include "types.h" #include "types.h"
#include "errors.h" #include "errors.h"
#include "blowfish.h" #include "blowfish.h"
#include "dynload.h"

View File

@ -18,8 +18,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#define DEFINES_CIPHER_HANDLE 1
#include <config.h> #include <config.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -160,6 +158,7 @@ load_cipher_modules()
int any = 0; int any = 0;
if( !initialized ) { if( !initialized ) {
cipher_modules_constructor();
setup_cipher_table(); /* load static modules on the first call */ setup_cipher_table(); /* load static modules on the first call */
initialized = 1; initialized = 1;
return 1; return 1;

View File

@ -66,6 +66,7 @@ typedef struct {
int seq1; int seq1;
int seq2; int seq2;
void *sym; void *sym;
int reqalgo;
} ENUMCONTEXT; } ENUMCONTEXT;
@ -323,6 +324,7 @@ enum_gnupgext_digests( void **enum_context,
if( !*enum_context ) { /* init context */ if( !*enum_context ) { /* init context */
ctx = m_alloc_clear( sizeof( *ctx ) ); ctx = m_alloc_clear( sizeof( *ctx ) );
ctx->r = extensions; ctx->r = extensions;
ctx->reqalgo = *algo;
*enum_context = ctx; *enum_context = ctx;
} }
else if( !algo ) { /* release the context */ else if( !algo ) { /* release the context */
@ -333,6 +335,7 @@ enum_gnupgext_digests( void **enum_context,
else else
ctx = *enum_context; ctx = *enum_context;
/* fixme: have a look at the hint string */
for( r = ctx->r; r; r = r->next ) { for( r = ctx->r; r; r = r->next ) {
int class, vers; int class, vers;

View File

@ -20,6 +20,8 @@
#ifndef G10_CIPHER_DYNLOAD_H #ifndef G10_CIPHER_DYNLOAD_H
#define G10_CIPHER_DYNLOAD_H #define G10_CIPHER_DYNLOAD_H
#include "mpi.h"
void register_internal_cipher_extension( const char *module_id, void register_internal_cipher_extension( const char *module_id,
void * (*enumfunc)(int, int*, int*, int*) ); void * (*enumfunc)(int, int*, int*, int*) );
@ -60,4 +62,7 @@ void (*dynload_getfnc_fast_random_poll(void)
)( void (*)(const void*, size_t, int), int ); )( void (*)(const void*, size_t, int), int );
/** This function is in construct.c **/
void cipher_modules_constructor(void);
#endif /*G10_CIPHER_DYNLOAD_H*/ #endif /*G10_CIPHER_DYNLOAD_H*/

View File

@ -18,8 +18,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#define DEFINES_MD_HANDLE 1
#include <config.h> #include <config.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -30,8 +28,6 @@
#include "cipher.h" #include "cipher.h"
#include "errors.h" #include "errors.h"
#include "dynload.h" #include "dynload.h"
#include "md5.h"
#include "sha1.h"
#include "rmd.h" #include "rmd.h"
@ -57,7 +53,6 @@ struct md_digest_list_s {
static struct md_digest_list_s *digest_list; static struct md_digest_list_s *digest_list;
static struct md_digest_list_s * static struct md_digest_list_s *
new_list_item( int algo, new_list_item( int algo,
const char *(*get_info)( int, size_t*,byte**, int*, int*, const char *(*get_info)( int, size_t*,byte**, int*, int*,
@ -79,33 +74,19 @@ new_list_item( int algo,
return r; return r;
} }
/****************
* Put the static entries into the table.
*/
static void
setup_digest_list()
{
struct md_digest_list_s *r;
r = new_list_item( DIGEST_ALGO_MD5, md5_get_info );
if( r ) { r->next = digest_list; digest_list = r; }
r = new_list_item( DIGEST_ALGO_RMD160, rmd160_get_info );
if( r ) { r->next = digest_list; digest_list = r; }
r = new_list_item( DIGEST_ALGO_SHA1, sha1_get_info );
if( r ) { r->next = digest_list; digest_list = r; }
}
/**************** /****************
* Try to load all modules and return true if new modules are available * Try to load the modules with the requeste algorithm
* and return true if new modules are available
* If req_alog is -1 try to load all digest algorithms.
*/ */
static int static int
load_digest_modules() load_digest_module( int req_algo )
{ {
static int done = 0;
static int initialized = 0; static int initialized = 0;
static u32 checked_algos[256/32];
static int checked_all = 0;
struct md_digest_list_s *r; struct md_digest_list_s *r;
void *context = NULL; void *context = NULL;
int algo; int algo;
@ -116,16 +97,24 @@ load_digest_modules()
void (**)(void*),byte *(**)(void*)); void (**)(void*),byte *(**)(void*));
if( !initialized ) { if( !initialized ) {
setup_digest_list(); /* load static modules on the first call */ cipher_modules_constructor();
initialized = 1; initialized = 1;
return 1;
} }
algo = req_algo;
if( done ) if( algo > 255 || !algo )
return 0; return 0; /* algorithm number too high (does not fit into out bitmap)*/
done = 1; if( checked_all )
return 0; /* already called with -1 */
if( algo < 0 )
checked_all = 1;
else if( (checked_algos[algo/32] & (1 << (algo%32))) )
return 0; /* already checked and not found */
else
checked_algos[algo/32] |= (1 << (algo%32));
while( enum_gnupgext_digests( &context, &algo, &get_info ) ) { while( enum_gnupgext_digests( &context, &algo, &get_info ) ) {
if( req_algo != -1 && algo != req_algo )
continue;
for(r=digest_list; r; r = r->next ) for(r=digest_list; r; r = r->next )
if( r->algo == algo ) if( r->algo == algo )
break; break;
@ -144,6 +133,8 @@ load_digest_modules()
r->next = digest_list; r->next = digest_list;
digest_list = r; digest_list = r;
any = 1; any = 1;
if( req_algo != -1 )
break;
} }
enum_gnupgext_digests( &context, NULL, NULL ); enum_gnupgext_digests( &context, NULL, NULL );
return any; return any;
@ -163,7 +154,7 @@ string_to_digest_algo( const char *string )
for(r = digest_list; r; r = r->next ) for(r = digest_list; r; r = r->next )
if( !stricmp( r->name, string ) ) if( !stricmp( r->name, string ) )
return r->algo; return r->algo;
} while( !r && load_digest_modules() ); } while( !r && load_digest_module(-1) );
return 0; return 0;
} }
@ -180,7 +171,7 @@ digest_algo_to_string( int algo )
for(r = digest_list; r; r = r->next ) for(r = digest_list; r; r = r->next )
if( r->algo == algo ) if( r->algo == algo )
return r->name; return r->name;
} while( !r && load_digest_modules() ); } while( !r && load_digest_module( algo ) );
return NULL; return NULL;
} }
@ -194,7 +185,7 @@ check_digest_algo( int algo )
for(r = digest_list; r; r = r->next ) for(r = digest_list; r; r = r->next )
if( r->algo == algo ) if( r->algo == algo )
return 0; return 0;
} while( !r && load_digest_modules() ); } while( !r && load_digest_module(algo) );
return G10ERR_DIGEST_ALGO; return G10ERR_DIGEST_ALGO;
} }
@ -241,7 +232,7 @@ md_enable( MD_HANDLE h, int algo )
for(r = digest_list; r; r = r->next ) for(r = digest_list; r; r = r->next )
if( r->algo == algo ) if( r->algo == algo )
break; break;
} while( !r && load_digest_modules() ); } while( !r && load_digest_module( algo ) );
if( !r ) { if( !r ) {
log_error("md_enable: algorithm %d not available\n", algo ); log_error("md_enable: algorithm %d not available\n", algo );
return; return;
@ -456,7 +447,7 @@ md_digest_length( int algo )
if( r->algo == algo ) if( r->algo == algo )
return r->mdlen; return r->mdlen;
} }
} while( !r && load_digest_modules() ); } while( !r && load_digest_module( algo ) );
log_error("WARNING: no length for md algo %d\n", algo); log_error("WARNING: no length for md algo %d\n", algo);
return 0; return 0;
} }
@ -479,7 +470,7 @@ md_asn_oid( int algo, size_t *asnlen, size_t *mdlen )
return r->asnoid; return r->asnoid;
} }
} }
} while( !r && load_digest_modules() ); } while( !r && load_digest_module( algo ) );
log_bug("no asn for md algo %d\n", algo); log_bug("no asn for md algo %d\n", algo);
return NULL; return NULL;
} }

View File

@ -34,8 +34,8 @@
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include "util.h" #include "util.h"
#include "md5.h"
#include "memory.h" #include "memory.h"
#include "dynload.h"
typedef struct { typedef struct {
@ -338,7 +338,7 @@ md5_read( MD5_CONTEXT *hd )
* Returns: A pointer to string describing the algorithm or NULL if * Returns: A pointer to string describing the algorithm or NULL if
* the ALGO is invalid. * the ALGO is invalid.
*/ */
const char * static const char *
md5_get_info( int algo, size_t *contextsize, md5_get_info( int algo, size_t *contextsize,
byte **r_asnoid, int *r_asnlen, int *r_mdlen, byte **r_asnoid, int *r_asnlen, int *r_mdlen,
void (**r_init)( void *c ), void (**r_init)( void *c ),
@ -367,5 +367,58 @@ md5_get_info( int algo, size_t *contextsize,
} }
#ifndef IS_MODULE
static
#endif
const char * const gnupgext_version = "MD5 ($Revision$)";
static struct {
int class;
int version;
int value;
void (*func)(void);
} func_table[] = {
{ 10, 1, 0, (void(*)(void))md5_get_info },
{ 11, 1, 1 },
};
#ifndef IS_MODULE
static
#endif
void *
gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
{
void *ret;
int i = *sequence;
do {
if( i >= DIM(func_table) || i < 0 )
return NULL;
*class = func_table[i].class;
*vers = func_table[i].version;
switch( *class ) {
case 11: case 21: case 31: ret = &func_table[i].value; break;
default: ret = func_table[i].func; break;
}
i++;
} while( what && what != *class );
*sequence = i;
return ret;
}
#ifndef IS_MODULE
void
md5_constructor(void)
{
register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func );
}
#endif
/* end of file */ /* end of file */

View File

@ -1,34 +0,0 @@
/* md5.h - message digest 5
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifndef G10_MD5_H
#define G10_MD5_H
const char *
md5_get_info( int algo, size_t *contextsize,
byte **r_asnoid, int *r_asn_len, int *r_mdlen,
void (**r_init)( void *c ),
void (**r_write)( void *c, byte *buf, size_t nbytes ),
void (**r_final)( void *c ),
byte *(**r_read)( void *c )
);
#endif /*G10_MD5_H*/

View File

@ -170,6 +170,7 @@ load_pubkey_modules()
if( !initialized ) { if( !initialized ) {
cipher_modules_constructor();
setup_pubkey_table(); setup_pubkey_table();
initialized = 1; initialized = 1;
return 1; return 1;

View File

@ -116,16 +116,7 @@ initialize()
keypool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN) keypool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN)
: m_alloc_clear(POOLSIZE+BLOCKLEN); : m_alloc_clear(POOLSIZE+BLOCKLEN);
is_initialized = 1; is_initialized = 1;
cipher_modules_constructor();
#if USE_RNDLINUX
rndlinux_constructor();
#elif USE_RNDUNIX
rndunix_constructor();
#elif USE_RNDW32
#elif USE_RNDOS2
#elif USE_RNDATARI
#elif USE_RNDMVS
#endif
} }
void void

View File

@ -32,16 +32,4 @@ typedef struct {
void rmd160_init( RMD160_CONTEXT *hd ); void rmd160_init( RMD160_CONTEXT *hd );
void rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ); void rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer );
const char *
rmd160_get_info( int algo, size_t *contextsize,
byte **r_asnoid, int *r_asn_len, int *r_mdlen,
void (**r_init)( void *c ),
void (**r_write)( void *c, byte *buf, size_t nbytes ),
void (**r_final)( void *c ),
byte *(**r_read)( void *c )
);
#endif /*G10_RMD_H*/ #endif /*G10_RMD_H*/

View File

@ -27,6 +27,7 @@
#include "memory.h" #include "memory.h"
#include "rmd.h" #include "rmd.h"
#include "cipher.h" /* only used for the rmd160_hash_buffer() prototype */ #include "cipher.h" /* only used for the rmd160_hash_buffer() prototype */
#include "dynload.h"
/********************************* /*********************************
* RIPEMD-160 is not patented, see (as of 25.10.97) * RIPEMD-160 is not patented, see (as of 25.10.97)
@ -554,7 +555,7 @@ rmd160_hash_buffer( char *outbuf, const char *buffer, size_t length )
* Returns: A pointer to string describing the algorithm or NULL if * Returns: A pointer to string describing the algorithm or NULL if
* the ALGO is invalid. * the ALGO is invalid.
*/ */
const char * static const char *
rmd160_get_info( int algo, size_t *contextsize, rmd160_get_info( int algo, size_t *contextsize,
byte **r_asnoid, int *r_asnlen, int *r_mdlen, byte **r_asnoid, int *r_asnlen, int *r_mdlen,
void (**r_init)( void *c ), void (**r_init)( void *c ),
@ -582,3 +583,63 @@ rmd160_get_info( int algo, size_t *contextsize,
return "RIPEMD160"; return "RIPEMD160";
} }
#ifndef IS_MODULE
static
#endif
const char * const gnupgext_version = "RMD160 ($Revision$)";
static struct {
int class;
int version;
int value;
void (*func)(void);
} func_table[] = {
{ 10, 1, 0, (void(*)(void))rmd160_get_info },
{ 11, 1, 3 },
};
#ifndef IS_MODULE
static
#endif
void *
gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
{
void *ret;
int i = *sequence;
do {
if( i >= DIM(func_table) || i < 0 ) {
return NULL;
}
*class = func_table[i].class;
*vers = func_table[i].version;
switch( *class ) {
case 11:
case 21:
case 31:
ret = &func_table[i].value;
break;
default:
ret = func_table[i].func;
break;
}
i++;
} while( what && what != *class );
*sequence = i;
return ret;
}
#ifndef IS_MODULE
void
rmd160_constructor(void)
{
register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func );
}
#endif

View File

@ -642,6 +642,9 @@ start_gatherer( int pipefd )
select(0, NULL, NULL, NULL, &tv); select(0, NULL, NULL, NULL, &tv);
continue; continue;
} }
if( errno == EPIPE ) /* parent has exited, so give up */
exit(0);
/* we can't do very much here because stderr is closed */ /* we can't do very much here because stderr is closed */
if( dbgfp ) if( dbgfp )
fprintf(dbgfp, "gatherer can't write to pipe: %s\n", fprintf(dbgfp, "gatherer can't write to pipe: %s\n",

View File

@ -38,7 +38,7 @@
#include <assert.h> #include <assert.h>
#include "util.h" #include "util.h"
#include "memory.h" #include "memory.h"
#include "sha1.h" #include "dynload.h"
typedef struct { typedef struct {
@ -331,7 +331,7 @@ sha1_read( SHA1_CONTEXT *hd )
* Returns: A pointer to string describing the algorithm or NULL if * Returns: A pointer to string describing the algorithm or NULL if
* the ALGO is invalid. * the ALGO is invalid.
*/ */
const char * static const char *
sha1_get_info( int algo, size_t *contextsize, sha1_get_info( int algo, size_t *contextsize,
byte **r_asnoid, int *r_asnlen, int *r_mdlen, byte **r_asnoid, int *r_asnlen, int *r_mdlen,
void (**r_init)( void *c ), void (**r_init)( void *c ),
@ -358,3 +358,64 @@ sha1_get_info( int algo, size_t *contextsize,
return "SHA1"; return "SHA1";
} }
#ifndef IS_MODULE
static
#endif
const char * const gnupgext_version = "SHA1 ($Revision$)";
static struct {
int class;
int version;
int value;
void (*func)(void);
} func_table[] = {
{ 10, 1, 0, (void(*)(void))sha1_get_info },
{ 11, 1, 2 },
};
#ifndef IS_MODULE
static
#endif
void *
gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
{
void *ret;
int i = *sequence;
do {
if( i >= DIM(func_table) || i < 0 ) {
return NULL;
}
*class = func_table[i].class;
*vers = func_table[i].version;
switch( *class ) {
case 11:
case 21:
case 31:
ret = &func_table[i].value;
break;
default:
ret = func_table[i].func;
break;
}
i++;
} while( what && what != *class );
*sequence = i;
return ret;
}
#ifndef IS_MODULE
void
sha1_constructor(void)
{
register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func );
}
#endif

View File

@ -1,33 +0,0 @@
/* sha1.h - SHA1 hash function
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifndef G10_SHA1_H
#define G10_SHA1_H
const char *
sha1_get_info( int algo, size_t *contextsize,
byte **r_asnoid, int *r_asn_len, int *r_mdlen,
void (**r_init)( void *c ),
void (**r_write)( void *c, byte *buf, size_t nbytes ),
void (**r_final)( void *c ),
byte *(**r_read)( void *c )
);
#endif /*G10_SHA1_H*/

View File

@ -909,6 +909,9 @@ tiger_get_info( int algo, size_t *contextsize,
#ifndef IS_MODULE
static
#endif
const char * const gnupgext_version = "TIGER ($Revision$)"; const char * const gnupgext_version = "TIGER ($Revision$)";
static struct { static struct {
@ -938,6 +941,9 @@ static struct {
* version = interface version of the function/pointer * version = interface version of the function/pointer
* (currently this is 1 for all functions) * (currently this is 1 for all functions)
*/ */
#ifndef IS_MODULE
static
#endif
void * void *
gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
{ {
@ -969,5 +975,17 @@ gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
return ret; return ret;
} }
#ifndef IS_MODULE
void
tiger_constructor(void)
{
register_internal_cipher_extension( gnupgext_version,
gnupgext_enum_func );
}
#endif
#endif /* HAVE_U64_TYPEDEF */ #endif /* HAVE_U64_TYPEDEF */

View File

@ -24,6 +24,7 @@
#include "types.h" /* for byte and u32 typedefs */ #include "types.h" /* for byte and u32 typedefs */
#include "util.h" #include "util.h"
#include "errors.h" #include "errors.h"
#include "dynload.h"
/* Prototype for the self-test function. */ /* Prototype for the self-test function. */
@ -462,7 +463,7 @@ twofish_setkey (TWOFISH_context *ctx, const byte *key, const unsigned keylen)
static const char *selftest_failed=0; static const char *selftest_failed=0;
/* Check key length. */ /* Check key length. */
if( keylen != 16 ) if( keylen != 16 ) /* enhance this code for 256 bit keys */
return G10ERR_WRONG_KEYLEN; return G10ERR_WRONG_KEYLEN;
/* Do self-test if necessary. */ /* Do self-test if necessary. */
@ -840,16 +841,18 @@ twofish_get_info (int algo, size_t *keylen,
void (**r_decrypt) (void *c, byte *outbuf, byte *inbuf) void (**r_decrypt) (void *c, byte *outbuf, byte *inbuf)
) )
{ {
*keylen = 128; *keylen = algo==10? 256 : 128;
*blocksize = 16; *blocksize = 16;
*contextsize = sizeof (TWOFISH_context); *contextsize = sizeof (TWOFISH_context);
*r_setkey = FNCCAST_SETKEY (twofish_setkey); *r_setkey = FNCCAST_SETKEY (twofish_setkey);
*r_encrypt= FNCCAST_CRYPT (twofish_encrypt); *r_encrypt= FNCCAST_CRYPT (twofish_encrypt);
*r_decrypt= FNCCAST_CRYPT (twofish_decrypt); *r_decrypt= FNCCAST_CRYPT (twofish_decrypt);
if( algo == 10 )
return "TWOFISH";
if (algo == 102) /* This algorithm number is assigned for if (algo == 102) /* This algorithm number is assigned for
* experiments, so we can use it */ * experiments, so we can use it */
return "TWOFISH"; return "TWOFISH128";
return NULL; return NULL;
} }
@ -863,6 +866,7 @@ static struct {
void (*func)(void); void (*func)(void);
} func_table[] = { } func_table[] = {
{ 20, 1, 0, (void(*)(void))twofish_get_info }, { 20, 1, 0, (void(*)(void))twofish_get_info },
{ 21, 1, 10 },
{ 21, 1, 102 }, { 21, 1, 102 },
}; };

View File

@ -15,11 +15,15 @@ AM_CONFIG_HEADER(config.h)
VERSION=`cat $srcdir/VERSION` VERSION=`cat $srcdir/VERSION`
PACKAGE=gnupg PACKAGE=gnupg
ALL_LINGUAS="de es_ES fr it pl pt_BR ru" ALL_LINGUAS="de es_ES fr it pl pt_BR ru"
static_modules="sha1 md5 rmd160"
AC_SUBST(VERSION) AC_SUBST(VERSION)
AC_SUBST(PACKAGE) AC_SUBST(PACKAGE)
AC_DEFINE_UNQUOTED(VERSION, "$VERSION") AC_DEFINE_UNQUOTED(VERSION, "$VERSION")
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE") AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
MODULES_IN_CIPHER=`awk '/# MODULES: / { for(i=3;i<=NF;i++) print $i}' \
$srcdir/cipher/Makefile.am`
AC_MSG_CHECKING([whether use of /dev/random is requested]) AC_MSG_CHECKING([whether use of /dev/random is requested])
AC_ARG_ENABLE(dev-random, AC_ARG_ENABLE(dev-random,
[ --disable-dev-random disable the use of dev random], [ --disable-dev-random disable the use of dev random],
@ -91,6 +95,8 @@ if test "$GCC" = yes; then
CFLAGS="$CFLAGS -Wall" CFLAGS="$CFLAGS -Wall"
fi fi
try_gettext=yes
try_gdbm=yes
case "${target}" in case "${target}" in
i386--mingw32) i386--mingw32)
# special stuff for Windoze NT # special stuff for Windoze NT
@ -99,9 +105,19 @@ case "${target}" in
CPP="i386--mingw32-gcc -E" CPP="i386--mingw32-gcc -E"
RANLIB="i386--mingw32-ranlib" RANLIB="i386--mingw32-ranlib"
ac_cv_have_dev_random=no ac_cv_have_dev_random=no
AC_DEFINE(USE_RNDW32)
AC_DEFINE(USE_ONLY_8DOT3) AC_DEFINE(USE_ONLY_8DOT3)
AC_DEFINE(HAVE_DRIVE_LETTERS) AC_DEFINE(HAVE_DRIVE_LETTERS)
AC_DEFINE(HAVE_DOSISH_SYSTEM)
try_gettext="no"
try_gdbm="no"
;;
i386-emx-os2)
# OS/2 with the EMX environment
ac_cv_have_dev_random=no
AC_DEFINE(HAVE_DRIVE_LETTERS)
AC_DEFINE(HAVE_DOSISH_SYSTEM)
try_gettext="no"
try_gdbm="no"
;; ;;
*-*-hpux*) *-*-hpux*)
if test -z "$GCC" ; then if test -z "$GCC" ; then
@ -126,6 +142,9 @@ case "${target}" in
i386--mingw32) i386--mingw32)
PRINTABLE_OS_NAME="MingW32" PRINTABLE_OS_NAME="MingW32"
;; ;;
i386-emx-os2)
PRINTABLE_OS_NAME="OS/2"
;;
*-linux*) *-linux*)
PRINTABLE_OS_NAME="GNU/Linux" PRINTABLE_OS_NAME="GNU/Linux"
;; ;;
@ -154,9 +173,13 @@ AC_DEFINE_UNQUOTED(NAME_OF_DEV_URANDOM, "$NAME_OF_DEV_URANDOM")
dnl Checks for libraries. dnl Checks for libraries.
if test "$try_gettext" = yes; then
AM_GNU_GETTEXT AM_GNU_GETTEXT
fi
if test "$try_gdbm" = yes; then
AC_CHECK_LIB(gdbm,gdbm_firstkey) AC_CHECK_LIB(gdbm,gdbm_firstkey)
fi
if test "$try_dynload" = yes ; then if test "$try_dynload" = yes ; then
@ -252,7 +275,6 @@ AC_CACHE_CHECK(for random device, ac_cv_have_dev_random,
ac_cv_have_dev_random=yes; else ac_cv_have_dev_random=no; fi]) ac_cv_have_dev_random=yes; else ac_cv_have_dev_random=no; fi])
if test "$ac_cv_have_dev_random" = yes; then if test "$ac_cv_have_dev_random" = yes; then
AC_DEFINE(HAVE_DEV_RANDOM) AC_DEFINE(HAVE_DEV_RANDOM)
AC_DEFINE(USE_RNDLINUX)
fi fi
else else
AC_MSG_CHECKING(for random device) AC_MSG_CHECKING(for random device)
@ -262,42 +284,93 @@ fi
dnl dnl
dnl Figure how to link the random modules dnl Figure out the default linkage mode for cipher modules
dnl dnl
dnl (We always need a static rmd160)
static_modules="$static_modules rmd160"
if test "$ac_cv_have_dev_random" = yes; then if test "$ac_cv_have_dev_random" = yes; then
AC_DEFINE(USE_RNDLINUX) static_modules="$static_modules rndlinux"
STATIC_RANDOM_OBJS="rndlinux.o"
DYNAMIC_RANDOM_MODS=""
else else
case "${target}" in case "${target}" in
i386--mingw32) i386--mingw32)
AC_DEFINE(USE_RNDW32) static_modules="$static_modules rndw32"
STATIC_RANDOM_OBJS="" ;;
DYNAMIC_RANDOM_MODS="" i386-emx-os2)
static_modules="$static_modules rndos2"
;; ;;
m68k-atari-mint) m68k-atari-mint)
AC_DEFINE(USE_RNDATARI) static_modules="$static_modules rndatari"
STATIC_RANDOM_OBJS=""
DYNAMIC_RANDOM_MODS=""
;; ;;
*) *)
AC_DEFINE(USE_RNDUNIX) static_modules="$static_modules rndunix"
STATIC_RANDOM_OBJS="rndunix.o"
DYNAMIC_RANDOM_MODS=""
;; ;;
esac esac
fi fi
AC_SUBST(STATIC_RANDOM_OBJS) dnl
AC_SUBST(DYNAMIC_RANDOM_MODS) dnl Parse the modules list and build the list
dnl of static and dymically linked modules
dnl
STATIC_CIPHER_NAMES=""
STATIC_CIPHER_OBJS=""
DYNAMIC_CIPHER_MODS=""
GNUPG_MSG_PRINT([dynamically linked cipher modules:])
for name in $MODULES_IN_CIPHER; do
x="no"
for i in $static_modules; do
if test "$name" = "$i" ; then
x="yes"
fi
done;
if test $x = yes; then
STATIC_CIPHER_NAMES="$STATIC_CIPHER_NAMES $name"
STATIC_CIPHER_OBJS="$STATIC_CIPHER_OBJS $name.o"
else
DYNAMIC_CIPHER_MODS="$DYNAMIC_CIPHER_MODS $name"
GNUPG_MSG_PRINT([$name])
fi
done
AC_MSG_RESULT()
AC_SUBST(STATIC_CIPHER_OBJS)
AC_SUBST(STATIC_CIPHER_NAMES)
AC_SUBST(DYNAMIC_CIPHER_MODS)
dnl
dnl And build the constructor file
dnl
cat <<EOF >cipher/construct.c
/* automatically generated by configure - do not edit */
EOF
GNUPG_MSG_PRINT([statically linked cipher modules:])
for name in $STATIC_CIPHER_NAMES; do
echo "void ${name}_constructor(void);" >>cipher/construct.c
GNUPG_MSG_PRINT([$name])
done
AC_MSG_RESULT()
cat <<EOF >>cipher/construct.c
void
cipher_modules_constructor(void)
{
static int done = 0;
if( done )
return;
done = 1;
EOF
for name in $STATIC_CIPHER_NAMES; do
echo " ${name}_constructor();" >>cipher/construct.c
done
echo '}' >>cipher/construct.c
dnl dnl
dnl Figure how to link the cipher modules dnl Figure how to link the cipher modules
dnl dnl
dnl (form now these are only dynamic) dnl (form now these are only dynamic)
STATIC_CIPHER_OBJS=""
DYNAMIC_CIPHER_MODS="twofish tiger"
AC_SUBST(STATIC_CIPHER_OBJS) AC_SUBST(STATIC_CIPHER_OBJS)
AC_SUBST(DYNAMIC_CIPHER_MODS) AC_SUBST(DYNAMIC_CIPHER_MODS)
@ -351,6 +424,10 @@ fi
fi fi
AC_SUBST(ZLIBS) AC_SUBST(ZLIBS)
if echo "$VERSION" | grep '[a-zA-Z]' >/dev/null ; then
AC_DEFINE(IS_DEVELOPMENT_VERSION)
fi
GNUPG_DO_LINK_FILES GNUPG_DO_LINK_FILES

View File

@ -79,7 +79,7 @@ more arguments in future versions.
The used key has been revoked by his owner. No arguments yet. The used key has been revoked by his owner. No arguments yet.
BADARMOR BADARMOR
The ascii armor is corrupted. No arguments yet. The ASCII armor is corrupted. No arguments yet.
RSA_OR_IDEA RSA_OR_IDEA
The RSA or IDEA algorithms has been used in the data. A The RSA or IDEA algorithms has been used in the data. A
@ -175,7 +175,7 @@ Record type 2: (directory record)
1 u32 cache record 1 u32 cache record
1 byte ownertrust 1 byte ownertrust
1 byte dirflag 1 byte dirflag
1 byte validity 1 byte validity of the key calucalted over all user ids
19 byte reserved 19 byte reserved
@ -208,7 +208,7 @@ Record type 4: (uid record)
1 u32 pointer to preference record 1 u32 pointer to preference record
1 u32 siglist list of valid signatures 1 u32 siglist list of valid signatures
1 byte uidflags 1 byte uidflags
1 byte reserved 1 byte validity of the key calculated over this user id
20 bytes ripemd160 hash of the username. 20 bytes ripemd160 hash of the username.
@ -418,7 +418,7 @@ Usage of gdbm files for keyrings
================================ ================================
The key to store the keyblock is it's fingerprint, other records The key to store the keyblock is it's fingerprint, other records
are used for secondary keys. fingerprints are always 20 bytes are used for secondary keys. fingerprints are always 20 bytes
where 16 bit fingerprints are appded with zero. where 16 bit fingerprints are appended with zero.
The first byte of the key gives some information on the type of the The first byte of the key gives some information on the type of the
key. key.
1 = key is a 20 bit fingerprint (16 bytes fpr are padded with zeroes) 1 = key is a 20 bit fingerprint (16 bytes fpr are padded with zeroes)

166
doc/FAQ
View File

@ -23,11 +23,10 @@
GNUPG is also useful for signing things. Things that are encrypted with GNUPG is also useful for signing things. Things that are encrypted with
the secret key can be decrypted with the public key. To sign something, a the secret key can be decrypted with the public key. To sign something, a
hash is taken of the data, and then the hash is in some form encoded hash is taken of the data, and then the hash is in some form encoded with
with the secret the secret key. If someone has your public key, they can verify that it
key. If someone has your public key, they can verify that it is from is from you and that it hasn't changed by checking the encoded form of
you and that it hasn't changed by checking the encoded form of the the hash with the public key.
hash with the public key.
A keyring is just a large file that stores keys. You have a public keyring A keyring is just a large file that stores keys. You have a public keyring
where you store yours and your friend's public keys. You have a secret where you store yours and your friend's public keys. You have a secret
@ -63,12 +62,12 @@
or at a meeting of your local GNU/Linux User Group. or at a meeting of your local GNU/Linux User Group.
Hmm, what else. You may use the option "-o filename" to force output Hmm, what else. You may use the option "-o filename" to force output
to this filename (use "-" to force output to stdout). to this filename (use "-" to force output to stdout). "-r" just lets you
"-r" just lets you specify the recipient (which public key you encrypt with) specify the recipient (which public key you encrypt with) on the command
on the command line instead of typing it interactively. line instead of typing it interactively.
Oh yeah, this is important. By default all data is encrypted in some weird Oh yeah, this is important. By default all data is encrypted in some weird
binary format. If you want to have things appear in ascii text that is binary format. If you want to have things appear in ASCII text that is
readable, just add the '-a' option. But the preferred method is to use readable, just add the '-a' option. But the preferred method is to use
a MIME aware mail reader (Mutt, Pine and many more). a MIME aware mail reader (Mutt, Pine and many more).
@ -94,31 +93,31 @@
a v3 packet. GNUPG is the only program which had used a v3 packet. GNUPG is the only program which had used
these v3 ElGamal keys - so this assumption is quite safe. these v3 ElGamal keys - so this assumption is quite safe.
Q: Why is PGP 5.x not able to encrypt messages with my public key. Q: Why is PGP 5.x not able to encrypt messages with my public key?
A: PGP Inc refuses to accept ElGamal keys of type 20 even for A: PGP Inc refuses to accept ElGamal keys of type 20 even for
encryption. They only supports type 16 (which are identical encryption. They only supports type 16 (which are identical
at least for decryption). To be better interoperable, GNUPG at least for decryption). To be more inter-operable, GNUPG
(starting with version 0.3.3) now also uses type 16 for the (starting with version 0.3.3) now also uses type 16 for the
ElGamal subkey which is created if the default key algorithm ElGamal subkey which is created if the default key algorithm
is chosen. You may add an type 16 ElGamal key to your public is chosen. You may add an type 16 ElGamal key to your public
key which is easy as your key signatures are still valid. key which is easy as your key signatures are still valid.
Q: Why is PGP 5.x not able to verify my messages. Q: Why is PGP 5.x not able to verify my messages?
A: PGP 5.x does not accept V4 signatures for data material but A: PGP 5.x does not accept V4 signatures for data material but
OpenPGP requires generation of V3 signatures for all kind of OpenPGP requires generation of V3 signatures for all kind of
data. Use the option "--force-v3-sigs" to generate V3 signatures data. Use the option "--force-v3-sigs" to generate V3 signatures
for data. for data.
Q: I can't delete an user id because it is already deleted on my Q: I can't delete an user id because it is already deleted on my
public keyring. public keyring?
A: Because you can only select from the public key ring, there is A: Because you can only select from the public key ring, there is
no direct way to do this. However it is not so complicated no direct way to do this. However it is not very complicated
do to it anyway: Create a new user id with exactly the same name, to do it anyway. Create a new user id with exactly the same name
you will notice that there are two identical user ids on the and you will see that there are now two identical user ids on the
secret ring now. Now select this user id and delete it; both secret ring. Now select this user id and delete it. Both user
user ids from the secret ring will be removed. ids will be removed from the secret ring.
Q: How can I encrypt a message in way pgp 2.x is able to decrypt it later? Q: How can I encrypt a message so that pgp 2.x is able to decrypt it?
A: You can't do that because pgp 2.x normally uses IDEA which is not A: You can't do that because pgp 2.x normally uses IDEA which is not
supported by GNUPG because it is patented, but if you have a modified supported by GNUPG because it is patented, but if you have a modified
version of PGP you can try this: version of PGP you can try this:
@ -130,11 +129,11 @@
gpg -c --cipher-algo 3des --compress-algo 1 --no-comment myfile gpg -c --cipher-algo 3des --compress-algo 1 --no-comment myfile
You may replace "3des" by "cast5"; "blowfish" does not work with You may replace "3des" by "cast5". "blowfish" does not work with
all versions of pgp5. You may also want to put all versions of pgp5. You may also want to put
no-comment no-comment
compress-algo 1 compress-algo 1
into your ~/.gnupg/options file - this does not affect the normal into your ~/.gnupg/options file - this does not affect normal
gnupg operation. gnupg operation.
@ -142,42 +141,40 @@
A: The problem here is that we need a lot of random bytes and for that A: The problem here is that we need a lot of random bytes and for that
we (on Linux the /dev/random device) must collect some random data. we (on Linux the /dev/random device) must collect some random data.
It is really not easy to fill the Linux internal entropy buffer; I It is really not easy to fill the Linux internal entropy buffer; I
talked to Ted Ts'o and he commited that the best way to fill the talked to Ted Ts'o and he commented that the best way to fill the buffer
buffer is to play with your keyboard. is to play with your keyboard. Good security has it's price. What I do
Good security has it's price. is to hit several times on the shift, control, alternate, and capslock
What I do is to hit several times on the shift,control, alternate, keys, because these keys do not produce output to the screen. This way
capslock keys, as these keys do not produce any output to the screen. you get your keys really fast (it's the same thing pgp2 does).
This way you get your keys really fast (it's the same thing pgp2 does).
Another problem might be another program which eats up your random bytes Another problem might be another program which eats up your random bytes
(a program (look at your daemons) that reads from /dev/[u]random). (a program (look at your daemons) that reads from /dev/[u]random).
Q: And it really takes long when I work on a remote system. Why? Q: And it really takes long when I work on a remote system. Why?
A: Don't do this at all! A: Don't do this at all! You should never create keys or even use gnupg
You should never create keys or even use gnupg on a remote system because on a remote system because you normally have no physical control over
you normally have your secret keyring (which is in most cases vulnerable to advanced
no physical control over your secret keyring (which is in most cases dictionary attacks) - I strongly encourage everyone to only create keys
vulnerable to advanced dictionary attacks) - I strongly encourage on a local computer (a disconnected laptop is probably the best choice)
everyone to only create keys on a local computer (a disconnected and if you need it on your connected box (I know: We all do this) be
laptop is probably the best choice) and if you need it on your sure to have a strong password for your account and for your secret key
connected box (I know: We all do this) be sure to have a strong and trust your Root.
password for your account, your secret key and trust your Root.
When I check gnupg on a remote system via ssh (I have no Alpha here ;-) When I check gnupg on a remote system via ssh (I have no Alpha here ;-)
I have the same problem too: it takes *very* long to create the keys, I have the same problem. It takes a *very* long time to create the
so I use a special option --quick-random to generate insecure keys which are keys, so I use a special option, --quick-random, to generate insecure
only good for some tests. keys which are only good for some tests.
Q: How does the whole trust thing work? Q: How does the whole trust thing work?
A: It works more or less like PGP. The difference is, that the trust is A: It works more or less like PGP. The difference is that the trust is
computed at the time it is needed; this is one of the reasons for the computed at the time it is needed. This is one of the reasons for the
trustdb which holds a list of valid key signatures. If you are not trustdb which holds a list of valid key signatures. If you are not
running in batch mode you will be asked to assign a trust parameter running in batch mode you will be asked to assign a trust parameter
(ownertrust) to a key. I have plans to use a cache for calculated (ownertrust) to a key. I have plans to use a cache for calculated
trust values to speed up calculation. trust values to speed up calculation.
You can see the validity (calculated trust value) using this command: You can see the validity (calculated trust value) using this command.
gpgm --list-keys --with-colons gpgm --list-keys --with-colons
@ -193,13 +190,13 @@
is only used for keys for which is only used for keys for which
the secret key is also available. the secret key is also available.
You can get a list of the assigned trust values (how far you trust You can get a list of the assigned trust values (how much you trust
the owner to correctly sign another one's key) the owner to correctly sign another person's key)
gpgm --list-ownertrust gpgm --list-ownertrust
The first field is the fingerprint of the primary key, the second one The first field is the fingerprint of the primary key, the second field
the assigned value: is the assigned value:
- = No Ownertrust value yet assigned. - = No Ownertrust value yet assigned.
n = Never trust this keyholder to correctly verify others signatures. n = Never trust this keyholder to correctly verify others signatures.
@ -207,42 +204,42 @@
f = Assume that the key holder really knows how to sign keys. f = Assume that the key holder really knows how to sign keys.
u = No need to trust ourself because we have the secret key. u = No need to trust ourself because we have the secret key.
Please keep these values confidential, as they express some opinions of Keep these values confidential because they express your opinions
you about others. PGP does store these information with the keyring, so about others. PGP stores this information with the keyring thus
it is not a good idea to publish the keyring instead of exporting the it is not a good idea to publish a PGP keyring instead of exporting the
keyring - gnupg stores the trust in the trust-DB and therefor it is okay keyring. gnupg stores the trust in the trust-DB so it is okay
to give the keyring away (but we have a --export command too). to give a gpg keyring away (but we have a --export command too).
Q: What is the difference between options and commands? Q: What is the difference between options and commands?
A: If you do a "gpg --help", you will get two separate lists. The first is a list A: If you do a "gpg --help", you will get two separate lists. The first is
of commands. The second is a list of options. Whenever you run GPG, you *must* a list of commands. The second is a list of options. Whenever you run GPG,
pick exactly one command (**with one exception, see below). You *may* pick one you *must* pick exactly one command (**with one exception, see below). You
or more options. The command should, just by convention, come at the end of the *may* pick one or more options. The command should, just by convention,
argument list, after all the options. If the command takes a file (all the come at the end of the argument list, after all the options. If the
basic ones do), the filename comes at the very end. So the basic way to command takes a file (all the basic ones do), the filename comes at the
run gpg is: very end. So the basic way to run gpg is:
gpg [--option something] [--option2] [--option3 something] --command file gpg [--option something] [--option2] [--option3 something] --command file
Some options take arguments, for example the --output option (which can be Some options take arguments, for example the --output option (which can be
abbreviated -o) is an option which takes a filename. The option's argument abbreviated -o) is an option that takes a filename. The option's argument
must follow immediately after the option itself: otherwise gpg doesn't know must follow immediately after the option itself, otherwise gpg doesn't know
which option the argument is supposed to go with. As an option, --output and which option the argument is supposed to go with. As an option, --output and
its filename must come before the command. The --remote-user (-r) option takes its filename must come before the command. The --remote-user (-r) option takes
a name or keyid to encrypt the message to, which must come right after the -r a name or keyid to encrypt the message to, which must come right after the -r
argument. The --encrypt (or -e) command comes after all the options, followed argument. The --encrypt (or -e) command comes after all the options followed
by the file you wish to encrypt. So use: by the file you wish to encrypt. So use
gpg -r alice -o secret.txt -e test.txt gpg -r alice -o secret.txt -e test.txt
If you write the options out in full, it is easier to read: If you write the options out in full, it is easier to read
gpg --remote-user alice --output secret.txt --encrypt test.txt gpg --remote-user alice --output secret.txt --encrypt test.txt
If you're saving it in a file called ".txt" then you'd probably expect to see If you're saving it in a file called ".txt" then you'd probably expect to see
ascii-armored text in there, so you need to add the --armor (-a) option, ASCII-armored text in there, so you need to add the --armor (-a) option,
which doesn't take any arguments: which doesn't take any arguments.
gpg --armor --remote-user alice --output secret.txt --encrypt test.txt gpg --armor --remote-user alice --output secret.txt --encrypt test.txt
@ -251,7 +248,7 @@
gpg [--armor] [--remote-user alice] [--output secret.txt] --encrypt test.txt gpg [--armor] [--remote-user alice] [--output secret.txt] --encrypt test.txt
The optional parts can be rearranged any way you want: The optional parts can be rearranged any way you want.
gpg --output secret.txt --remote-user alice --armor --encrypt test.txt gpg --output secret.txt --remote-user alice --armor --encrypt test.txt
@ -268,30 +265,30 @@
Q: What kind of output is this: "key C26EE891.298, uid 09FB: ...."? Q: What kind of output is this: "key C26EE891.298, uid 09FB: ...."?
A: This is the internal representation of an user id in the trustdb. A: This is the internal representation of an user id in the trustdb.
"C26EE891" is the keyid, "298" is the local id (a record number "C26EE891" is the keyid, "298" is the local id (a record number
in the trustdb) and "09FB" are the last two bytes of a ripe-md-160 in the trustdb) and "09FB" is the last two bytes of a ripe-md-160
hash of the user id for this key. hash of the user id for this key.
Q: What is trust, validity and ownertrust? Q: What is trust, validity and ownertrust?
A: "ownertrust" is used instead of "trust" to make clear that A: "ownertrust" is used instead of "trust" to make clear that
this is the value you have assigned to key to express, how far you this is the value you have assigned to key to express how much you
trust the owner of this key to correctly sign (and so introduce) trust the owner of this key to correctly sign (and so introduce)
other keys. "validity" or calculated trust is a value which other keys. "validity", or calculated trust, is a value which
says, how far the gnupg thinks a key is valid (that it really belongs says how much the gnupg thinks a key is valid (that it really belongs
to the one who claims to be the owner of the key). to the one who claims to be the owner of the key).
For more see the chapter "The Web of Trust" in the For more see the chapter "The Web of Trust" in the
Manual [gpg: Oops: Internal error: manual not found - sorry] Manual [gpg: Oops: Internal error: manual not found - sorry]
Q: How do interpret some of the informational outputs: Q: How do interpret some of the informational outputs?
A: While checking the validness of a key, GnuPG sometimes print A: While checking the validity of a key, GnuPG sometimes prints
some informations which are prefixed with information about some information which is prefixed with information about
the checked item: the checked item.
"key 12345678.3456" "key 12345678.3456"
This is about the key with key ID 12345678 and the internal This is about the key with key ID 12345678 and the internal
number 3456, which is the record number of the so called number 3456, which is the record number of the so called
directory record in the trustdb. directory record in the trustdb.
"uid 12345678.3456/ACDE" "uid 12345678.3456/ACDE"
This is about the user ID for the same key; to identify the This is about the user ID for the same key. To identify the
user ID the last two bytes of a ripe-md-160 over the user ID user ID the last two bytes of a ripe-md-160 over the user ID
ring is printed. ring is printed.
"sig 12345678.3456/ACDE/9A8B7C6D" "sig 12345678.3456/ACDE/9A8B7C6D"
@ -302,15 +299,14 @@
Q: How do I sign a patch file? Q: How do I sign a patch file?
A: Use "gpg --clearsign --not-dash-escaped ...". A: Use "gpg --clearsign --not-dash-escaped ...".
The problem with --clearsign is The problem with --clearsign is that all lines starting with a dash are
that all lines starting with a dash are quoted with "- "; obviously quoted with "- "; obviously diff produces many of lines starting with a
diff produces many of lines starting with a dash and these are dash and these are then quoted and that is not good for patch ;-). To
then quoted and that is not good for patch ;-). In order to use use a patch file without removing the cleartext signature, the special
a patch file without removing the cleartext signature, the special option --not-dash-escaped may be used to suppress generation of these
option --not-dash-escaped may be used to suppress generation of escape sequences. You should not mail such a patch because spaces and
these escape sequences. You should not mail such a patch because line endings are also subject to the signature and a mailer may not
spaces and line endings are also subject to the signature and a mailer preserve these. If you want to mail a file you can simply sign it
may not preserve these. If you want to mail a file you can simply sign using your MUA.
it using your MUA.

View File

@ -67,7 +67,7 @@ B<-k> [I<username>] [I<keyring>]
Kludge to be somewhat compatible with PGP. Kludge to be somewhat compatible with PGP.
Without arguments, all public keyrings are listed. Without arguments, all public keyrings are listed.
With one argument, only I<keyring> is listed. With one argument, only I<keyring> is listed.
Special combinations are also allowed, but it may Special combinations are also allowed, but they may
give strange results when combined with more options. give strange results when combined with more options.
B<-kv> Same as B<-k> B<-kv> Same as B<-k>
B<-kvv> List the signatures with every key. B<-kvv> List the signatures with every key.
@ -130,7 +130,7 @@ B<--edit-key> I<name>
Remove a subkey. Remove a subkey.
B<expire> B<expire>
Change the key expiration time. If a key is Change the key expiration time. If a key is
select, the time of this key will be changed. selected, the time of this key will be changed.
With no selection the key expiration of the With no selection the key expiration of the
primary key is changed. primary key is changed.
B<passwd> B<passwd>
@ -154,10 +154,10 @@ B<--edit-key> I<name>
key rings. key rings.
The listing shows you the key with its secondary The listing shows you the key with its secondary
keys and all user ids. Selected keys or user ids keys and all user ids. Selected keys or user ids
indicated by an asterisk. The trust value is are indicated by an asterisk. The trust value is
displayed with the primary key: The first one is the displayed with the primary key: the first is the
assigned owner trust and the second the calculated assigned owner trust and the second is the calculated
trust value; letters are used for the values: trust value. Letters are used for the values:
B<-> No ownertrust assigned / not yet calculated. B<-> No ownertrust assigned / not yet calculated.
B<e> Trust calculation has failed. B<e> Trust calculation has failed.
B<q> Not enough information for calculation. B<q> Not enough information for calculation.
@ -201,11 +201,11 @@ B<--export-secret-keys> [I<names>]
B<--import>, B<--fast-import> B<--import>, B<--fast-import>
Import/merge keys. The fast version does not build Import/merge keys. The fast version does not build
the trustdb; this can be deon at anytime with the the trustdb; this can be done at any time with the
command B<--update-trustdb>. command B<--update-trustdb>.
B<--export-ownertrust> B<--export-ownertrust>
List the assigned ownertrust values in ascii format List the assigned ownertrust values in ASCII format
for backup purposes [B<gpgm> only]. for backup purposes [B<gpgm> only].
B<--import-ownertrust> [I<filename>] B<--import-ownertrust> [I<filename>]
@ -215,9 +215,9 @@ B<--import-ownertrust> [I<filename>]
=head1 OPTIONS =head1 OPTIONS
Long options can be put in an options file (default F<~/.gnupg/options>); Long options can be put in an options file (default F<~/.gnupg/options>).
do not write the 2 dashes, but simply the name of the option and any Do not write the 2 dashes, but simply the name of the option and any
arguments if required. Lines with a hash as the first non-white-space required arguments. Lines with a hash as the first non-white-space
character are ignored. Commands may be put in this file too, but that character are ignored. Commands may be put in this file too, but that
does not make sense. does not make sense.
@ -250,7 +250,7 @@ B<--trusted-key> I<keyid>
You may also use this option to skip the verification You may also use this option to skip the verification
of your own secret keys which is normally done every of your own secret keys which is normally done every
time GnuPG starts up: Use for I<keyid> the one of time GnuPG starts up by using the I<keyid> of
your key. your key.
B<-r> I<name>, B<--recipient> I<name> B<-r> I<name>, B<--recipient> I<name>
@ -268,7 +268,7 @@ B<-q>, B<--quiet>
B<-z> I<n> B<-z> I<n>
Set compress level to I<n>. A value of 0 for I<n> Set compress level to I<n>. A value of 0 for I<n>
disables compression. Default is to use the default disables compression. Default is to use the default
compression level of zlib (which is 6). compression level of zlib (normally 6).
B<-t>, B<--textmode> B<-t>, B<--textmode>
Use canonical text mode. If B<-t> (but not Use canonical text mode. If B<-t> (but not
@ -276,17 +276,17 @@ B<-t>, B<--textmode>
and signing, this enables clearsigned messages. and signing, this enables clearsigned messages.
This kludge is needed for PGP compatibility; This kludge is needed for PGP compatibility;
normally you would use B<--sign> or B<--clearsign> normally you would use B<--sign> or B<--clearsign>
to selected the type os signatures. to selected the type of the signature.
B<-n>, B<--dry-run> B<-n>, B<--dry-run>
Don't make any changes (not yet implemented). Don't make any changes (not yet implemented).
B<--batch> B<--batch>
Batch mode; never ask, do not allow interactive Use batch mode. Never ask, do not allow interactive
commands. commands.
B<--no-batch> B<--no-batch>
Disable batch mode; this may be used if B<batch> Disable batch mode. This may be used if B<batch>
is used in the options file. is used in the options file.
B<--yes> B<--yes>
@ -297,7 +297,7 @@ B<--no>
B<--keyserver> I<name> B<--keyserver> I<name>
Use I<name> to lookup keys which are not yet in Use I<name> to lookup keys which are not yet in
your keyring; this is only done while verifying your keyring. This is only done while verifying
messages with signatures. The option is also messages with signatures. The option is also
required for the command B<--send-keys> to required for the command B<--send-keys> to
specify the keyserver to where the keys should specify the keyserver to where the keys should
@ -374,11 +374,11 @@ B<--set-filename> I<string>
B<--completes-needed> I<n> B<--completes-needed> I<n>
Number of completely trusted users to introduce a new Number of completely trusted users to introduce a new
key signator (defaults to 1). key signer (defaults to 1).
B<--marginals-needed> I<n> B<--marginals-needed> I<n>
Number of marginally trusted users to introduce a new Number of marginally trusted users to introduce a new
key signator (defaults to 3) key signer (defaults to 3)
B<--max-cert-depth> I<n> B<--max-cert-depth> I<n>
Maximum depth of a certification chain (default is 5). Maximum depth of a certification chain (default is 5).
@ -409,7 +409,7 @@ B<--s2k-digest-algo> I<name>
encryption if B<--digest-algo> is not given. encryption if B<--digest-algo> is not given.
B<--s2k-mode> I<number> B<--s2k-mode> I<number>
Selects how passphrases are mangled: A number of I<0> Selects how passphrases are mangled. A number of I<0>
uses the plain passphrase (which is not recommended), uses the plain passphrase (which is not recommended),
a I<1> (default) adds a salt to the passphrase and a I<1> (default) adds a salt to the passphrase and
I<3> iterates the whole process a couple of times. I<3> iterates the whole process a couple of times.
@ -418,12 +418,12 @@ B<--s2k-mode> I<number>
B<--compress-algo> I<number> B<--compress-algo> I<number>
Use compress algorithm I<number>. Default is I<2> which is Use compress algorithm I<number>. Default is I<2> which is
RFC1950 compression; you may use I<1> to use the old zlib RFC1950 compression. You may use I<1> to use the old zlib
version which is used by PGP. version which is used by PGP. The default algorithm may
The default algorithm may give better give better results because the window size is not limited
results because the window size is not limited to 8K. to 8K. If this is not used the OpenPGP behavior is used,
If this is not used the OpenPGP behavior is used; i.e. i.e. the compression algorithm is selected from the
the compression algorithm is selected from the preferences. preferences.
B<--digest-algo> I<name> B<--digest-algo> I<name>
Use I<name> as message digest algorithm. Running the Use I<name> as message digest algorithm. Running the
@ -438,21 +438,20 @@ B<--throw-keyid>
process because all available secret keys are tried. process because all available secret keys are tried.
B<--not-dash-escaped> B<--not-dash-escaped>
This option changes the behavior of cleartext signature This option changes the behavior of cleartext signatures
so that they can be used for patch files. You should not so that they can be used for patch files. You should not
send such an armored file via email because all spaces send such an armored file via email because all spaces
and line endings are hashed too. You can not use this and line endings are hashed too. You can not use this
option for data which has 5 dashes somewhere at the option for data which has 5 dashes at the beginning of a
beginning of a line - patch files don't have this. line, patch files don't have this. A special armor header
A special armor header line tells GnuPG about this line tells GnuPG about this cleartext signature option.
cleartext signature framework.
B<--escape-from-lines> B<--escape-from-lines>
Because some mailers change lines starting with "From " Because some mailers change lines starting with "From "
to ">From " it is good to handle such lines in a special to ">From " it is good to handle such lines in a special
way when creating cleartext signatures; all other PGP way when creating cleartext signatures. All other PGP
versions do it this way too. Because this would violate versions do it this way too. This option is not enabled
rfc2440, this option is not enabled per default. by default because it would violate rfc2440.
B<--passphrase-fd> I<n> B<--passphrase-fd> I<n>
Read the passphrase from file descriptor I<n>. If you use Read the passphrase from file descriptor I<n>. If you use
@ -464,10 +463,10 @@ B<--rfc1991>
Try to be more RFC1991 (PGP 2.x) compliant. Try to be more RFC1991 (PGP 2.x) compliant.
B<--force-v3-sigs> B<--force-v3-sigs>
OpenPGP states that a implementation should generate OpenPGP states that an implementation should generate
v4 signatures but PGP 5.x does only recognize such v4 signatures but PGP 5.x recognizes v4 signatures only
signatures on key material. This options forces on key material. This options forces v3 signatures for
v3 signatures for signatures on data. signatures on data.
B<--lock-once> B<--lock-once>
Lock the file the first time a lock is requested Lock the file the first time a lock is requested
@ -510,7 +509,7 @@ B<-h>, B<--help>
=head1 RETURN VALUE =head1 RETURN VALUE
The Program returns 0 if everything was fine, 1 if at least The Program returns 0 if everything was fine, 1 if at least
a signature was bad and other errorcode for fatal errors. a signature was bad, and other error codes for fatal errors.
=head1 EXAMPLES =head1 EXAMPLES
@ -552,15 +551,15 @@ Use a B<good> password for your user account and a B<good> passphrase
to protect your secret key. This passphrase is the weakest part of the to protect your secret key. This passphrase is the weakest part of the
whole system. Programs to do dictionary attacks on your secret keyring whole system. Programs to do dictionary attacks on your secret keyring
are very easy to write and so you should protect your B<~/.gnupg/> are very easy to write and so you should protect your B<~/.gnupg/>
directory very good. directory very well.
Keep in mind that, if this program is used over a network (telnet), it Keep in mind that, if this program is used over a network (telnet), it
is B<very> easy to spy out your passphrase! is B<very> easy to spy out your passphrase!
=head1 BUGS =head1 BUGS
On many systems this program should be installed as setuid(root); this On many systems this program should be installed as setuid(root). This
is necessary to lock some pages of memory. If you get no warning message is necessary to lock memory pages. If you get no warning message about
about insecure memory your OS kernel supports locking without being root; insecure memory your OS kernel supports locking without being root.
setuid is dropped as soon as this memory is allocated. The program drops root privileges as soon as locked memory is allocated.

View File

@ -1,3 +1,25 @@
Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* g10.c (main): check for development version now in configure
* tdbio.c (tdbio_write_record): Add uid.validity
(tdbio_read_record) : Ditto.
(tdbio_dump_record) : Ditto.
* keygen.c (keygen_add_std_prefs): Replaced Blowfish by Twofish,
removed MD5 and Tiger.
* pubkey-enc.c (get_it): Suppress warning about missing Blowfish
in preferences in certain cases.
* ringedit.c (lock_rentry,unlock_rentry): New.
* getkey.c (key_byname): Pass ret_kb down to lookup_xx.
* armor.c (armor_filter): No output of of empty comment lines.
Add option --no-version to suppress the output of the version string.
* getkey.c: Release the getkey context for auto context variables.
Sun Jan 24 18:16:26 CET 1999 Werner Koch <wk@isil.d.shuttle.de> Sun Jan 24 18:16:26 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* getkey.c: Changed the internal design to allow simultaneous * getkey.c: Changed the internal design to allow simultaneous

View File

@ -876,23 +876,26 @@ armor_filter( void *opaque, int control,
iobuf_writestr(a, "-----"); iobuf_writestr(a, "-----");
iobuf_writestr(a, head_strings[afx->what] ); iobuf_writestr(a, head_strings[afx->what] );
iobuf_writestr(a, "-----\n"); iobuf_writestr(a, "-----\n");
iobuf_writestr(a, "Version: GnuPG v" VERSION " (" if( !opt.no_version )
PRINTABLE_OS_NAME ")\n"); iobuf_writestr(a, "Version: GnuPG v" VERSION " ("
PRINTABLE_OS_NAME ")\n");
if( opt.comment_string ) { if( opt.comment_string ) {
const char *s = opt.comment_string; const char *s = opt.comment_string;
iobuf_writestr(a, "Comment: " ); if( *s ) {
for( ; *s; s++ ) { iobuf_writestr(a, "Comment: " );
if( *s == '\n' ) for( ; *s; s++ ) {
iobuf_writestr(a, "\\n" ); if( *s == '\n' )
else if( *s == '\r' ) iobuf_writestr(a, "\\n" );
iobuf_writestr(a, "\\r" ); else if( *s == '\r' )
else if( *s == '\v' ) iobuf_writestr(a, "\\r" );
iobuf_writestr(a, "\\v" ); else if( *s == '\v' )
else iobuf_writestr(a, "\\v" );
iobuf_put(a, *s ); else
iobuf_put(a, *s );
}
iobuf_put(a, '\n' );
} }
iobuf_put(a, '\n' );
} }
else else
iobuf_writestr(a, iobuf_writestr(a,

View File

@ -117,6 +117,7 @@ enum cmd_and_opt_values { aNull = 0,
oDebugAll, oDebugAll,
oStatusFD, oStatusFD,
oNoComment, oNoComment,
oNoVersion,
oCompletesNeeded, oCompletesNeeded,
oMarginalsNeeded, oMarginalsNeeded,
oMaxCertDepth, oMaxCertDepth,
@ -307,6 +308,7 @@ static ARGPARSE_OPTS opts[] = {
{ oRunAsShmCP, "run-as-shm-coprocess", 4, "@" }, { oRunAsShmCP, "run-as-shm-coprocess", 4, "@" },
{ oSetFilename, "set-filename", 2, "@" }, { oSetFilename, "set-filename", 2, "@" },
{ oComment, "comment", 2, "@" }, { oComment, "comment", 2, "@" },
{ oNoVersion, "no-version", 0, "@"},
{ oNotDashEscaped, "not-dash-escaped", 0, "@" }, { oNotDashEscaped, "not-dash-escaped", 0, "@" },
{ oEscapeFrom, "escape-from-lines", 0, "@" }, { oEscapeFrom, "escape-from-lines", 0, "@" },
{ oLockOnce, "lock-once", 0, "@" }, { oLockOnce, "lock-once", 0, "@" },
@ -716,6 +718,7 @@ main( int argc, char **argv )
opt.verbose = 0; opt.list_sigs=0; break; opt.verbose = 0; opt.list_sigs=0; break;
case oQuickRandom: quick_random_gen(1); break; case oQuickRandom: quick_random_gen(1); break;
case oNoComment: opt.no_comment=1; break; case oNoComment: opt.no_comment=1; break;
case oNoVersion: opt.no_version=1; break;
case oCompletesNeeded: opt.completes_needed = pargs.r.ret_int; break; case oCompletesNeeded: opt.completes_needed = pargs.r.ret_int; break;
case oMarginalsNeeded: opt.marginals_needed = pargs.r.ret_int; break; case oMarginalsNeeded: opt.marginals_needed = pargs.r.ret_int; break;
case oMaxCertDepth: opt.max_cert_depth = pargs.r.ret_int; break; case oMaxCertDepth: opt.max_cert_depth = pargs.r.ret_int; break;
@ -810,6 +813,9 @@ main( int argc, char **argv )
if( greeting ) { if( greeting ) {
tty_printf("%s %s; %s\n", strusage(11), strusage(13), strusage(14) ); tty_printf("%s %s; %s\n", strusage(11), strusage(13), strusage(14) );
tty_printf("%s\n", strusage(15) ); tty_printf("%s\n", strusage(15) );
#ifdef IS_DEVELOPMENT_VERSION
log_info("NOTE: this is a development version!\n");
#endif
} }
secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */ secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */
@ -859,12 +865,6 @@ main( int argc, char **argv )
log_error(_("invalid S2K mode; must be 0, 1 or 3\n")); log_error(_("invalid S2K mode; must be 0, 1 or 3\n"));
} }
{ const char *p = strusage(13);
for( ; *p && (isdigit(*p) || *p=='.'); p++ )
;
if( *p )
log_info("NOTE: this is a development version!\n");
}
if( log_get_errorcount(0) ) if( log_get_errorcount(0) )
g10_exit(2); g10_exit(2);

View File

@ -38,9 +38,9 @@
#define MAX_PK_CACHE_ENTRIES 50 #define MAX_PK_CACHE_ENTRIES 50
#define MAX_UID_CACHE_ENTRIES 50 #define MAX_UID_CACHE_ENTRIES 50
/* Aa map of the all characters valid used for word_match() /* A map of the all characters valid used for word_match()
* Valid characters are in in this table converted to uppercase. * Valid characters are in in this table converted to uppercase.
* becuase the upper 128 bytes have special meanin, we assume * because the upper 128 bytes have special meaning, we assume
* that they are all valid. * that they are all valid.
* Note: We must use numerical values here in case that this program * Note: We must use numerical values here in case that this program
* will be converted to those little blue HAL9000s with their strange * will be converted to those little blue HAL9000s with their strange
@ -95,6 +95,7 @@ struct getkey_ctx_s {
KBPOS kbpos; KBPOS kbpos;
int last_rc; int last_rc;
ulong count; ulong count;
int not_allocated;
int nitems; int nitems;
getkey_item_t items[1]; getkey_item_t items[1];
}; };
@ -322,11 +323,13 @@ get_pubkey( PKT_public_key *pk, u32 *keyid )
/* do a lookup */ /* do a lookup */
{ struct getkey_ctx_s ctx; { struct getkey_ctx_s ctx;
memset( &ctx, 0, sizeof ctx ); memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.nitems = 1; ctx.nitems = 1;
ctx.items[0].mode = 11; ctx.items[0].mode = 11;
ctx.items[0].keyid[0] = keyid[0]; ctx.items[0].keyid[0] = keyid[0];
ctx.items[0].keyid[1] = keyid[1]; ctx.items[0].keyid[1] = keyid[1];
rc = lookup_pk( &ctx, pk, NULL ); rc = lookup_pk( &ctx, pk, NULL );
get_pubkey_end( &ctx );
} }
if( !rc ) if( !rc )
goto leave; goto leave;
@ -371,11 +374,13 @@ get_seckey( PKT_secret_key *sk, u32 *keyid )
struct getkey_ctx_s ctx; struct getkey_ctx_s ctx;
memset( &ctx, 0, sizeof ctx ); memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.nitems = 1; ctx.nitems = 1;
ctx.items[0].mode = 11; ctx.items[0].mode = 11;
ctx.items[0].keyid[0] = keyid[0]; ctx.items[0].keyid[0] = keyid[0];
ctx.items[0].keyid[1] = keyid[1]; ctx.items[0].keyid[1] = keyid[1];
rc = lookup_sk( &ctx, sk, NULL ); rc = lookup_sk( &ctx, sk, NULL );
get_seckey_end( &ctx );
if( !rc ) { if( !rc ) {
/* check the secret key (this may prompt for a passprase to /* check the secret key (this may prompt for a passprase to
* unlock the secret key * unlock the secret key
@ -395,14 +400,18 @@ int
get_primary_seckey( PKT_secret_key *sk, u32 *keyid ) get_primary_seckey( PKT_secret_key *sk, u32 *keyid )
{ {
struct getkey_ctx_s ctx; struct getkey_ctx_s ctx;
int rc;
memset( &ctx, 0, sizeof ctx ); memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.primary = 1; ctx.primary = 1;
ctx.nitems = 1; ctx.nitems = 1;
ctx.items[0].mode = 11; ctx.items[0].mode = 11;
ctx.items[0].keyid[0] = keyid[0]; ctx.items[0].keyid[0] = keyid[0];
ctx.items[0].keyid[1] = keyid[1]; ctx.items[0].keyid[1] = keyid[1];
return lookup_sk( &ctx, sk, NULL ); rc = lookup_sk( &ctx, sk, NULL );
get_seckey_end( &ctx );
return rc;
} }
@ -421,11 +430,13 @@ seckey_available( u32 *keyid )
sk = m_alloc_clear( sizeof *sk ); sk = m_alloc_clear( sizeof *sk );
memset( &ctx, 0, sizeof ctx ); memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.nitems = 1; ctx.nitems = 1;
ctx.items[0].mode = 11; ctx.items[0].mode = 11;
ctx.items[0].keyid[0] = keyid[0]; ctx.items[0].keyid[0] = keyid[0];
ctx.items[0].keyid[1] = keyid[1]; ctx.items[0].keyid[1] = keyid[1];
rc = lookup_sk( &ctx, sk, NULL ); rc = lookup_sk( &ctx, sk, NULL );
get_seckey_end( &ctx );
free_secret_key( sk ); free_secret_key( sk );
return rc; return rc;
} }
@ -653,9 +664,9 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
/* and call the lookup function */ /* and call the lookup function */
ctx->primary = 1; /* we want to look for the primary key only */ ctx->primary = 1; /* we want to look for the primary key only */
if( sk ) if( sk )
rc = lookup_sk( ctx, sk, NULL ); rc = lookup_sk( ctx, sk, ret_kb );
else else
rc = lookup_pk( ctx, pk, NULL ); rc = lookup_pk( ctx, pk, ret_kb );
if( retctx ) /* caller wants the context */ if( retctx ) /* caller wants the context */
*retctx = ctx; *retctx = ctx;
@ -733,7 +744,8 @@ get_pubkey_end( GETKEY_CTX ctx )
enum_keyblocks( 2, &ctx->kbpos, NULL ); /* close */ enum_keyblocks( 2, &ctx->kbpos, NULL ); /* close */
for(n=0; n < ctx->nitems; n++ ) for(n=0; n < ctx->nitems; n++ )
m_free( ctx->items[n].namebuf ); m_free( ctx->items[n].namebuf );
m_free( ctx ); if( !ctx->not_allocated )
m_free( ctx );
} }
} }
@ -748,10 +760,12 @@ get_pubkey_byfprint( PKT_public_key *pk, const byte *fprint, size_t fprint_len)
if( fprint_len == 20 || fprint_len == 16 ) { if( fprint_len == 20 || fprint_len == 16 ) {
struct getkey_ctx_s ctx; struct getkey_ctx_s ctx;
memset( &ctx, 0, sizeof ctx ); memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.nitems = 1; ctx.nitems = 1;
ctx.items[0].mode = fprint_len; ctx.items[0].mode = fprint_len;
memcpy( ctx.items[0].fprint, fprint, fprint_len ); memcpy( ctx.items[0].fprint, fprint, fprint_len );
rc = lookup_pk( &ctx, pk, NULL ); rc = lookup_pk( &ctx, pk, NULL );
get_pubkey_end( &ctx );
} }
else else
rc = G10ERR_GENERAL; /* Oops */ rc = G10ERR_GENERAL; /* Oops */
@ -772,10 +786,12 @@ get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint,
if( fprint_len == 20 || fprint_len == 16 ) { if( fprint_len == 20 || fprint_len == 16 ) {
struct getkey_ctx_s ctx; struct getkey_ctx_s ctx;
memset( &ctx, 0, sizeof ctx ); memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.nitems = 1; ctx.nitems = 1;
ctx.items[0].mode = fprint_len; ctx.items[0].mode = fprint_len;
memcpy( ctx.items[0].fprint, fprint, fprint_len ); memcpy( ctx.items[0].fprint, fprint, fprint_len );
rc = lookup_pk( &ctx, pk, ret_keyblock ); rc = lookup_pk( &ctx, pk, ret_keyblock );
get_pubkey_end( &ctx );
} }
else else
rc = G10ERR_GENERAL; /* Oops */ rc = G10ERR_GENERAL; /* Oops */
@ -806,10 +822,12 @@ get_seckey_byname( PKT_secret_key *sk, const char *name, int unprotect )
struct getkey_ctx_s ctx; struct getkey_ctx_s ctx;
memset( &ctx, 0, sizeof ctx ); memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.primary = 1; ctx.primary = 1;
ctx.nitems = 1; ctx.nitems = 1;
ctx.items[0].mode = 15; ctx.items[0].mode = 15;
rc = lookup_sk( &ctx, sk, NULL ); rc = lookup_sk( &ctx, sk, NULL );
get_seckey_end( &ctx );
} }
else { else {
add_to_strlist( &namelist, name ); add_to_strlist( &namelist, name );
@ -868,7 +886,8 @@ get_seckey_end( GETKEY_CTX ctx )
enum_keyblocks( 2, &ctx->kbpos, NULL ); /* close */ enum_keyblocks( 2, &ctx->kbpos, NULL ); /* close */
for(n=0; n < ctx->nitems; n++ ) for(n=0; n < ctx->nitems; n++ )
m_free( ctx->items[n].namebuf ); m_free( ctx->items[n].namebuf );
m_free( ctx ); if( !ctx->not_allocated )
m_free( ctx );
} }
} }
@ -1600,7 +1619,7 @@ lookup_pk( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock )
k = find_first( ctx->keyblock, pk ); k = find_first( ctx->keyblock, pk );
else if( item->mode == 16 || item->mode == 20 ) else if( item->mode == 16 || item->mode == 20 )
k = find_by_fpr( ctx->keyblock, pk, k = find_by_fpr( ctx->keyblock, pk,
item->name, item->mode ); item->fprint, item->mode );
else else
BUG(); BUG();
if( k ) { if( k ) {
@ -1687,7 +1706,7 @@ lookup_sk( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock )
k = find_first_sk( ctx->keyblock, sk ); k = find_first_sk( ctx->keyblock, sk );
else if( item->mode == 16 || item->mode == 20 ) else if( item->mode == 16 || item->mode == 20 )
k = find_by_fpr_sk( ctx->keyblock, sk, k = find_by_fpr_sk( ctx->keyblock, sk,
item->name, item->mode ); item->fprint, item->mode );
else else
BUG(); BUG();
if( k ) { if( k ) {

View File

@ -83,15 +83,13 @@ keygen_add_std_prefs( PKT_signature *sig, void *opaque )
keygen_add_key_expire( sig, opaque ); keygen_add_key_expire( sig, opaque );
buf[0] = CIPHER_ALGO_BLOWFISH; buf[0] = CIPHER_ALGO_TWOFISH;
buf[1] = CIPHER_ALGO_CAST5; buf[1] = CIPHER_ALGO_CAST5;
build_sig_subpkt( sig, SIGSUBPKT_PREF_SYM, buf, 2 ); build_sig_subpkt( sig, SIGSUBPKT_PREF_SYM, buf, 2 );
buf[0] = DIGEST_ALGO_RMD160; buf[0] = DIGEST_ALGO_RMD160;
buf[1] = DIGEST_ALGO_SHA1; buf[1] = DIGEST_ALGO_SHA1;
buf[2] = DIGEST_ALGO_TIGER; build_sig_subpkt( sig, SIGSUBPKT_PREF_HASH, buf, 2 );
buf[3] = DIGEST_ALGO_MD5;
build_sig_subpkt( sig, SIGSUBPKT_PREF_HASH, buf, 4 );
buf[0] = 2; buf[0] = 2;
buf[1] = 1; buf[1] = 1;

View File

@ -169,6 +169,7 @@ list_keyblock( KBNODE keyblock, int secret )
node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY ); node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY );
if( !node ) { if( !node ) {
log_error("Oops; key lost!\n"); log_error("Oops; key lost!\n");
dump_kbnode( keyblock );
return; return;
} }

View File

@ -252,7 +252,11 @@ proc_plaintext( CTX c, PACKET *pkt )
free_md_filter_context( &c->mfx ); free_md_filter_context( &c->mfx );
c->mfx.md = md_open( 0, 0); c->mfx.md = md_open( 0, 0);
/* fixme: we may need to push the textfilter if we have sigclass 1 /* fixme: we may need to push the textfilter if we have sigclass 1
* and no armoring - Not yet tested */ * and no armoring - Not yet tested
* Hmmm, why don't we need it at all if we have sigclass 1
* Should we assume that plaintext in mode 't' has always sigclass 1??
* See: Russ Allbery's mail 1999-02-09
*/
any = clearsig = 0; any = clearsig = 0;
for(n=c->list; n; n = n->next ) { for(n=c->list; n; n = n->next ) {
if( n->pkt->pkttype == PKT_ONEPASS_SIG ) { if( n->pkt->pkttype == PKT_ONEPASS_SIG ) {

View File

@ -47,6 +47,7 @@ struct {
int def_compress_algo; int def_compress_algo;
const char *def_secret_key; const char *def_secret_key;
int no_comment; int no_comment;
int no_version;
int marginals_needed; int marginals_needed;
int completes_needed; int completes_needed;
int max_cert_depth; int max_cert_depth;

View File

@ -31,6 +31,7 @@
#include "trustdb.h" #include "trustdb.h"
#include "cipher.h" #include "cipher.h"
#include "status.h" #include "status.h"
#include "options.h"
#include "i18n.h" #include "i18n.h"
static int get_it( PKT_pubkey_enc *k, static int get_it( PKT_pubkey_enc *k,
@ -179,9 +180,17 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
else if( !pk->local_id && query_trust_record(pk) ) else if( !pk->local_id && query_trust_record(pk) )
log_error("can't check algorithm against preferences\n"); log_error("can't check algorithm against preferences\n");
else if( dek->algo != CIPHER_ALGO_3DES else if( dek->algo != CIPHER_ALGO_3DES
&& !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM, dek->algo ) ) && !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM, dek->algo ) ) {
log_info(_("NOTE: cipher algorithm %d not found in preferences\n"), /* Don't print a note while we are not on verbose mode,
* the cipher is blowfish and the preferences have twofish
* listed */
if( opt.verbose || dek->algo != CIPHER_ALGO_BLOWFISH
|| !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM,
CIPHER_ALGO_TWOFISH ) )
log_info(_(
"NOTE: cipher algorithm %d not found in preferences\n"),
dek->algo ); dek->algo );
}
free_public_key( pk ); free_public_key( pk );
rc = 0; rc = 0;
} }

View File

@ -72,12 +72,13 @@ struct resource_table_struct {
GDBM_FILE dbf; GDBM_FILE dbf;
#endif #endif
enum resource_type rt; enum resource_type rt;
DOTLOCK lockhd;
int is_locked;
}; };
typedef struct resource_table_struct RESTBL; typedef struct resource_table_struct RESTBL;
#define MAX_RESOURCES 10 #define MAX_RESOURCES 10
static RESTBL resource_table[MAX_RESOURCES]; static RESTBL resource_table[MAX_RESOURCES];
static const char *keyring_lock;
static int search( PACKET *pkt, KBPOS *kbpos, int secret ); static int search( PACKET *pkt, KBPOS *kbpos, int secret );
@ -117,15 +118,40 @@ fatal_gdbm_error( const char *string )
#endif /* HAVE_LIBGDBM */ #endif /* HAVE_LIBGDBM */
/****************
* Hmmm, how to avoid deadlock? They should not happen if everyone
* locks the key resources in the same order; but who knows.
* A solution is to use only one lock file in the gnupg homedir but
* what will happen with key resources which normally don't belong
* to the gpg homedir?
*/
static void static void
cleanup( void ) lock_rentry( RESTBL *rentry )
{ {
if( keyring_lock ) { if( !rentry->lockhd ) {
release_dotlock( keyring_lock ); rentry->lockhd = create_dotlock( rentry->fname );
keyring_lock = NULL; if( !rentry->lockhd )
log_fatal("can't allocate lock for `%s'\n", rentry->fname );
rentry->is_locked = 0;
}
if( !rentry->is_locked ) {
if( make_dotlock( rentry->lockhd, -1 ) )
log_fatal("can't lock `%s'\n", rentry->fname );
rentry->is_locked = 1;
} }
} }
static void
unlock_rentry( RESTBL *rentry )
{
if( opt.lock_once )
return;
if( !release_dotlock( rentry->lockhd ) )
rentry->is_locked = 0;
}
/**************************************************************** /****************************************************************
****************** public functions **************************** ****************** public functions ****************************
****************************************************************/ ****************************************************************/
@ -162,7 +188,6 @@ enum_keyblock_resources( int *sequence, int secret )
int int
add_keyblock_resource( const char *url, int force, int secret ) add_keyblock_resource( const char *url, int force, int secret )
{ {
static int initialized = 0;
static int any_secret, any_public; static int any_secret, any_public;
const char *resname = url; const char *resname = url;
IOBUF iobuf = NULL; IOBUF iobuf = NULL;
@ -171,10 +196,6 @@ add_keyblock_resource( const char *url, int force, int secret )
int rc = 0; int rc = 0;
enum resource_type rt = rt_UNKNOWN; enum resource_type rt = rt_UNKNOWN;
if( !initialized ) {
initialized = 1;
atexit( cleanup );
}
/* Do we have an URL? /* Do we have an URL?
* gnupg-gdbm:filename := this is a GDBM resource * gnupg-gdbm:filename := this is a GDBM resource
@ -190,7 +211,7 @@ add_keyblock_resource( const char *url, int force, int secret )
rt = rt_GDBM; rt = rt_GDBM;
resname += 11; resname += 11;
} }
#ifndef __MINGW32__ #ifndef HAVE_DRIVE_LETTERS
else if( strchr( resname, ':' ) ) { else if( strchr( resname, ':' ) ) {
log_error("%s: invalid URL\n", url ); log_error("%s: invalid URL\n", url );
rc = G10ERR_GENERAL; rc = G10ERR_GENERAL;
@ -264,7 +285,7 @@ add_keyblock_resource( const char *url, int force, int secret )
if( access(filename, F_OK) ) { if( access(filename, F_OK) ) {
if( strlen(filename) >= 7 if( strlen(filename) >= 7
&& !strcmp(filename+strlen(filename)-7, "/.gnupg") ) { && !strcmp(filename+strlen(filename)-7, "/.gnupg") ) {
#if __MINGW32__ #ifdef HAVE_DOSISH_SYSTEM
if( mkdir(filename) ) if( mkdir(filename) )
#else #else
if( mkdir(filename, S_IRUSR|S_IWUSR|S_IXUSR) ) if( mkdir(filename, S_IRUSR|S_IWUSR|S_IXUSR) )
@ -298,10 +319,10 @@ add_keyblock_resource( const char *url, int force, int secret )
else else
log_info(_("%s: keyring created\n"), filename ); log_info(_("%s: keyring created\n"), filename );
} }
#if __MINGW32__ || 1 #if HAVE_DOSISH_SYSTEM || 1
/* must close it again */
iobuf_close( iobuf ); iobuf_close( iobuf );
iobuf = NULL; iobuf = NULL;
/* must close it again */
#endif #endif
break; break;
@ -1039,7 +1060,7 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
kbpos->rt = rt_RING; kbpos->rt = rt_RING;
kbpos->valid = 0; kbpos->valid = 0;
#if __MINGW32__ || 1 #if HAVE_DOSISH_SYSTEM || 1
assert(!iobuf); assert(!iobuf);
iobuf = iobuf_open( fname ); iobuf = iobuf_open( fname );
if( !iobuf ) { if( !iobuf ) {
@ -1084,7 +1105,7 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
leave: leave:
free_packet(&pkt); free_packet(&pkt);
set_packet_list_mode(save_mode); set_packet_list_mode(save_mode);
#if __MINGW32__ || 1 #if HAVE_DOSISH_SYSTEM || 1
iobuf_close(iobuf); iobuf_close(iobuf);
#endif #endif
return rc; return rc;
@ -1276,10 +1297,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
if( kbpos->fp ) if( kbpos->fp )
BUG(); /* not allowed with such a handle */ BUG(); /* not allowed with such a handle */
if( !keyring_lock ); lock_rentry( rentry );
keyring_lock = make_dotlock( rentry->fname, -1 );
if( !keyring_lock )
log_fatal("can't lock `%s'\n", rentry->fname );
/* open the source file */ /* open the source file */
fp = iobuf_open( rentry->fname ); fp = iobuf_open( rentry->fname );
@ -1290,10 +1308,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
newfp = iobuf_create( rentry->fname ); newfp = iobuf_create( rentry->fname );
if( !newfp ) { if( !newfp ) {
log_error(_("%s: can't create: %s\n"), rentry->fname, strerror(errno)); log_error(_("%s: can't create: %s\n"), rentry->fname, strerror(errno));
if( !opt.lock_once ) { unlock_rentry( rentry );
release_dotlock( keyring_lock );
keyring_lock = NULL;
}
return G10ERR_OPEN_FILE; return G10ERR_OPEN_FILE;
} }
else else
@ -1305,28 +1320,19 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
log_error("build_packet(%d) failed: %s\n", log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, g10_errstr(rc) ); node->pkt->pkttype, g10_errstr(rc) );
iobuf_cancel(newfp); iobuf_cancel(newfp);
if( !opt.lock_once ) { unlock_rentry( rentry );
release_dotlock( keyring_lock );
keyring_lock = NULL;
}
return G10ERR_WRITE_FILE; return G10ERR_WRITE_FILE;
} }
} }
if( iobuf_close(newfp) ) { if( iobuf_close(newfp) ) {
log_error("%s: close failed: %s\n", rentry->fname, strerror(errno)); log_error("%s: close failed: %s\n", rentry->fname, strerror(errno));
if( !opt.lock_once ) { unlock_rentry( rentry );
release_dotlock( keyring_lock );
keyring_lock = NULL;
}
return G10ERR_CLOSE_FILE; return G10ERR_CLOSE_FILE;
} }
if( chmod( rentry->fname, S_IRUSR | S_IWUSR ) ) { if( chmod( rentry->fname, S_IRUSR | S_IWUSR ) ) {
log_error("%s: chmod failed: %s\n", log_error("%s: chmod failed: %s\n",
rentry->fname, strerror(errno) ); rentry->fname, strerror(errno) );
if( !opt.lock_once ) { unlock_rentry( rentry );
release_dotlock( keyring_lock );
keyring_lock = NULL;
}
return G10ERR_WRITE_FILE; return G10ERR_WRITE_FILE;
} }
return 0; return 0;
@ -1338,7 +1344,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
} }
/* create the new file */ /* create the new file */
#ifdef __MINGW32__ #ifdef USE_ONLY_8DOT3
/* Here is another Windoze bug?: /* Here is another Windoze bug?:
* you cant rename("pubring.gpg.tmp", "pubring.gpg"); * you cant rename("pubring.gpg.tmp", "pubring.gpg");
* but rename("pubring.gpg.tmp", "pubring.aaa"); * but rename("pubring.gpg.tmp", "pubring.aaa");
@ -1451,7 +1457,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
goto leave; goto leave;
} }
/* if the new file is a secring, restrict the permissions */ /* if the new file is a secring, restrict the permissions */
#ifndef __MINGW32__ #ifndef HAVE_DOSISH_SYSTEM
if( rentry->secret ) { if( rentry->secret ) {
if( chmod( tmpfname, S_IRUSR | S_IWUSR ) ) { if( chmod( tmpfname, S_IRUSR | S_IWUSR ) ) {
log_error("%s: chmod failed: %s\n", log_error("%s: chmod failed: %s\n",
@ -1464,7 +1470,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
/* rename and make backup file */ /* rename and make backup file */
if( !rentry->secret ) { /* but not for secret keyrings */ if( !rentry->secret ) { /* but not for secret keyrings */
#ifdef __MINGW32__ #ifdef HAVE_DOSISH_SYSTEM
remove( bakfname ); remove( bakfname );
#endif #endif
if( rename( rentry->fname, bakfname ) ) { if( rename( rentry->fname, bakfname ) ) {
@ -1474,7 +1480,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
goto leave; goto leave;
} }
} }
#ifdef __MINGW32__ #ifdef HAVE_DOSISH_SYSTEM
remove( rentry->fname ); remove( rentry->fname );
#endif #endif
if( rename( tmpfname, rentry->fname ) ) { if( rename( tmpfname, rentry->fname ) ) {
@ -1492,10 +1498,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
} }
leave: leave:
if( !opt.lock_once ) { unlock_rentry( rentry );
release_dotlock( keyring_lock );
keyring_lock = NULL;
}
m_free(bakfname); m_free(bakfname);
m_free(tmpfname); m_free(tmpfname);
return rc; return rc;

View File

@ -70,7 +70,7 @@ got_usr_signal( int sig )
caught_sigusr1 = 1; caught_sigusr1 = 1;
} }
#ifndef __MINGW32__ #ifndef HAVE_DOSISH_SYSTEM
static void static void
do_sigaction( int sig, struct sigaction *nact ) do_sigaction( int sig, struct sigaction *nact )
{ {
@ -85,7 +85,7 @@ do_sigaction( int sig, struct sigaction *nact )
void void
init_signals() init_signals()
{ {
#ifndef __MINGW32__ #ifndef HAVE_DOSISH_SYSTEM
struct sigaction nact; struct sigaction nact;
nact.sa_handler = got_fatal_signal; nact.sa_handler = got_fatal_signal;
@ -100,7 +100,7 @@ init_signals()
nact.sa_handler = got_usr_signal; nact.sa_handler = got_usr_signal;
sigaction( SIGUSR1, &nact, NULL ); sigaction( SIGUSR1, &nact, NULL );
nact.sa_handler = SIG_IGN; nact.sa_handler = SIG_IGN;
sigaction( SIGPIPE, &nact, NULL ); sigaction( SIGPIPE, &nact, NULL );
#endif #endif
} }
@ -108,7 +108,7 @@ init_signals()
void void
pause_on_sigusr( int which ) pause_on_sigusr( int which )
{ {
#ifndef __MINGW32__ #ifndef HAVE_DOSISH_SYSTEM
sigset_t mask, oldmask; sigset_t mask, oldmask;
assert( which == 1 ); assert( which == 1 );
@ -127,7 +127,7 @@ pause_on_sigusr( int which )
static void static void
do_block( int block ) do_block( int block )
{ {
#ifndef __MINGW32__ #ifndef HAVE_DOSISH_SYSTEM
static int is_blocked; static int is_blocked;
static sigset_t oldmask; static sigset_t oldmask;
@ -146,7 +146,7 @@ do_block( int block )
sigprocmask( SIG_SETMASK, &oldmask, NULL ); sigprocmask( SIG_SETMASK, &oldmask, NULL );
is_blocked = 0; is_blocked = 0;
} }
#endif /*__MINGW32__*/ #endif /*HAVE_DOSISH_SYSTEM*/
} }

View File

@ -77,7 +77,8 @@ struct cmp_sdir_struct {
static char *db_name; static char *db_name;
static const char *lockname; static DOTLOCK lockhandle;
static int is_locked;
static int db_fd = -1; static int db_fd = -1;
static int in_transaction; static int in_transaction;
@ -236,10 +237,12 @@ put_record_into_cache( ulong recno, const char *data )
int n = dirty_count / 5; /* discard some dirty entries */ int n = dirty_count / 5; /* discard some dirty entries */
if( !n ) if( !n )
n = 1; n = 1;
if( !lockname ) if( !is_locked ) {
lockname = make_dotlock( db_name, -1 ); if( make_dotlock( lockhandle, -1 ) )
if( !lockname ) log_fatal("can't acquire lock - giving up\n");
log_fatal("can't get a lock - giving up\n"); else
is_locked = 1;
}
for( unused = NULL, r = cache_list; r; r = r->next ) { for( unused = NULL, r = cache_list; r; r = r->next ) {
if( r->flags.used && r->flags.dirty ) { if( r->flags.used && r->flags.dirty ) {
int rc = write_cache_item( r ); int rc = write_cache_item( r );
@ -254,8 +257,8 @@ put_record_into_cache( ulong recno, const char *data )
} }
} }
if( !opt.lock_once ) { if( !opt.lock_once ) {
release_dotlock( lockname ); if( !release_dotlock( lockhandle ) )
lockname=NULL; is_locked = 0;
} }
assert( unused ); assert( unused );
r = unused; r = unused;
@ -287,17 +290,20 @@ tdbio_sync()
CACHE_CTRL r; CACHE_CTRL r;
int did_lock = 0; int did_lock = 0;
if( db_fd == -1 )
open_db();
if( in_transaction ) if( in_transaction )
log_bug("tdbio: syncing while in transaction\n"); log_bug("tdbio: syncing while in transaction\n");
if( !cache_is_dirty ) if( !cache_is_dirty )
return 0; return 0;
if( !lockname ) { if( !is_locked ) {
lockname = make_dotlock( db_name, -1 ); if( make_dotlock( lockhandle, -1 ) )
log_fatal("can't acquire lock - giving up\n");
else
is_locked = 1;
did_lock = 1; did_lock = 1;
if( !lockname )
log_fatal("can't get a lock - giving up\n");
} }
for( r = cache_list; r; r = r->next ) { for( r = cache_list; r; r = r->next ) {
if( r->flags.used && r->flags.dirty ) { if( r->flags.used && r->flags.dirty ) {
@ -308,8 +314,8 @@ tdbio_sync()
} }
cache_is_dirty = 0; cache_is_dirty = 0;
if( did_lock && !opt.lock_once ) { if( did_lock && !opt.lock_once ) {
release_dotlock( lockname ); if( !release_dotlock( lockhandle ) )
lockname=NULL; is_locked = 0;
} }
return 0; return 0;
} }
@ -344,17 +350,19 @@ tdbio_end_transaction()
if( !in_transaction ) if( !in_transaction )
log_bug("tdbio: no active transaction\n"); log_bug("tdbio: no active transaction\n");
if( !lockname ) if( !is_locked ) {
lockname = make_dotlock( db_name, -1 ); if( make_dotlock( lockhandle, -1 ) )
if( !lockname ) log_fatal("can't acquire lock - giving up\n");
log_fatal("can't get a lock - giving up\n"); else
is_locked = 1;
}
block_all_signals(); block_all_signals();
in_transaction = 0; in_transaction = 0;
rc = tdbio_sync(); rc = tdbio_sync();
unblock_all_signals(); unblock_all_signals();
if( !opt.lock_once ) { if( !opt.lock_once ) {
release_dotlock( lockname ); if( !release_dotlock( lockhandle ) )
lockname=NULL; is_locked = 0;
} }
return rc; return rc;
} }
@ -392,9 +400,9 @@ tdbio_cancel_transaction()
static void static void
cleanup(void) cleanup(void)
{ {
if( lockname ) { if( is_locked ) {
release_dotlock(lockname); if( !release_dotlock(lockhandle) )
lockname = NULL; is_locked = 0;
} }
} }
@ -428,7 +436,7 @@ tdbio_set_dbname( const char *new_dbname, int create )
if( access( fname, F_OK ) ) { if( access( fname, F_OK ) ) {
if( strlen(fname) >= 7 if( strlen(fname) >= 7
&& !strcmp(fname+strlen(fname)-7, "/.gnupg" ) ) { && !strcmp(fname+strlen(fname)-7, "/.gnupg" ) ) {
#if __MINGW32__ #if HAVE_DOSISH_SYSTEM
if( mkdir( fname ) ) if( mkdir( fname ) )
#else #else
if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) ) if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) )
@ -450,7 +458,7 @@ tdbio_set_dbname( const char *new_dbname, int create )
fclose(fp); fclose(fp);
m_free(db_name); m_free(db_name);
db_name = fname; db_name = fname;
#ifdef __MINGW32__ #ifdef HAVE_DOSISH_SYSTEM
db_fd = open( db_name, O_RDWR | O_BINARY ); db_fd = open( db_name, O_RDWR | O_BINARY );
#else #else
db_fd = open( db_name, O_RDWR ); db_fd = open( db_name, O_RDWR );
@ -501,7 +509,10 @@ open_db()
TRUSTREC rec; TRUSTREC rec;
assert( db_fd == -1 ); assert( db_fd == -1 );
#ifdef __MINGW32__ lockhandle = create_dotlock( db_name );
if( !lockhandle )
log_fatal( _("%s: can't create lock\n"), db_name );
#ifdef HAVE_DOSISH_SYSTEM
db_fd = open( db_name, O_RDWR | O_BINARY ); db_fd = open( db_name, O_RDWR | O_BINARY );
#else #else
db_fd = open( db_name, O_RDWR ); db_fd = open( db_name, O_RDWR );
@ -970,6 +981,8 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
rec->r.uid.prefrec, rec->r.uid.prefrec,
rec->r.uid.siglist, rec->r.uid.siglist,
rec->r.uid.namehash[18], rec->r.uid.namehash[19]); rec->r.uid.namehash[18], rec->r.uid.namehash[19]);
if( rec->r.uid.uidflags & UIDF_VALVALID )
fprintf( fp, ", v=%02x", rec->r.uid.validity );
if( rec->r.uid.uidflags & UIDF_CHECKED ) { if( rec->r.uid.uidflags & UIDF_CHECKED ) {
if( rec->r.uid.uidflags & UIDF_VALID ) if( rec->r.uid.uidflags & UIDF_VALID )
fputs(", valid", fp ); fputs(", valid", fp );
@ -1155,7 +1168,18 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
rec->r.uid.prefrec = buftoulong(p); p += 4; rec->r.uid.prefrec = buftoulong(p); p += 4;
rec->r.uid.siglist = buftoulong(p); p += 4; rec->r.uid.siglist = buftoulong(p); p += 4;
rec->r.uid.uidflags = *p++; rec->r.uid.uidflags = *p++;
p ++; rec->r.uid.validity = *p++;
switch( rec->r.uid.validity ) {
case 0:
case TRUST_UNDEFINED:
case TRUST_NEVER:
case TRUST_MARGINAL:
case TRUST_FULLY:
case TRUST_ULTIMATE:
break;
default:
log_info("lid %lu: invalid validity value - cleared\n", recnum);
}
memcpy( rec->r.uid.namehash, p, 20); memcpy( rec->r.uid.namehash, p, 20);
break; break;
case RECTYPE_PREF: /* preference record */ case RECTYPE_PREF: /* preference record */
@ -1278,7 +1302,7 @@ tdbio_write_record( TRUSTREC *rec )
ulongtobuf(p, rec->r.uid.prefrec); p += 4; ulongtobuf(p, rec->r.uid.prefrec); p += 4;
ulongtobuf(p, rec->r.uid.siglist); p += 4; ulongtobuf(p, rec->r.uid.siglist); p += 4;
*p++ = rec->r.uid.uidflags; *p++ = rec->r.uid.uidflags;
p++; *p++ = rec->r.uid.validity;
memcpy( p, rec->r.uid.namehash, 20 ); p += 20; memcpy( p, rec->r.uid.namehash, 20 ); p += 20;
break; break;

View File

@ -59,9 +59,10 @@
#define KEYF_EXPIRED 4 /* this key is expired */ #define KEYF_EXPIRED 4 /* this key is expired */
#define KEYF_REVOKED 8 /* this key has been revoked */ #define KEYF_REVOKED 8 /* this key has been revoked */
#define UIDF_CHECKED 1 /* user id has been checked - other bits are valid */ #define UIDF_CHECKED 1 /* user id has been checked - other bits are valid */
#define UIDF_VALID 2 /* this is a valid user id */ #define UIDF_VALID 2 /* this is a valid user id */
#define UIDF_REVOKED 8 /* this user id has been revoked */ #define UIDF_REVOKED 8 /* this user id has been revoked */
#define UIDF_VALVALID 16 /* the validity field is valid */
#define SIGF_CHECKED 1 /* signature has been checked - bits 0..6 are valid */ #define SIGF_CHECKED 1 /* signature has been checked - bits 0..6 are valid */
#define SIGF_VALID 2 /* the signature is valid */ #define SIGF_VALID 2 /* the signature is valid */
@ -98,7 +99,7 @@ struct trust_record {
ulong cacherec; /* the cache record */ ulong cacherec; /* the cache record */
byte ownertrust; byte ownertrust;
byte dirflags; byte dirflags;
byte validity; /* calculated trustlevel */ byte validity; /* calculated trustlevel over all uids */
} dir; } dir;
struct { /* primary public key record */ struct { /* primary public key record */
ulong lid; ulong lid;
@ -114,6 +115,7 @@ struct trust_record {
ulong prefrec; /* recno of preference record */ ulong prefrec; /* recno of preference record */
ulong siglist; /* list of valid signatures (w/o self-sig)*/ ulong siglist; /* list of valid signatures (w/o self-sig)*/
byte uidflags; byte uidflags;
byte validity; /* calculated trustlevel of this uid */
byte namehash[20]; /* ripemd hash of the username */ byte namehash[20]; /* ripemd hash of the username */
} uid; } uid;
struct { /* preference record */ struct { /* preference record */

View File

@ -104,6 +104,8 @@ static void release_lid_table( LOCAL_ID_TABLE tbl );
static int ins_lid_table_item( LOCAL_ID_TABLE tbl, ulong lid, unsigned flag ); static int ins_lid_table_item( LOCAL_ID_TABLE tbl, ulong lid, unsigned flag );
static int qry_lid_table_flag( LOCAL_ID_TABLE tbl, ulong lid, unsigned *flag ); static int qry_lid_table_flag( LOCAL_ID_TABLE tbl, ulong lid, unsigned *flag );
static void print_user_id( const char *text, u32 *keyid ); static void print_user_id( const char *text, u32 *keyid );
static void sort_tsl_list( TRUST_SEG_LIST *trust_seg_list ); static void sort_tsl_list( TRUST_SEG_LIST *trust_seg_list );
static int list_sigs( ulong pubkey_id ); static int list_sigs( ulong pubkey_id );
@ -839,42 +841,13 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
ulong rn, uidrn; ulong rn, uidrn;
int marginal=0; int marginal=0;
int fully=0; int fully=0;
LOCAL_ID_TABLE sigs_seen = NULL; /*LOCAL_ID_TABLE sigs_seen = NULL;*/
if( depth >= max_depth ) /* max cert_depth reached */ if( depth >= max_depth ) /* max cert_depth reached */
return TRUST_UNDEFINED; return TRUST_UNDEFINED;
stack[depth].lid = drec->r.dir.lid;
stack[depth].otrust = drec->r.dir.ownertrust;
stack[depth].trust = 0;
{ int i;
for(i=0; i < depth; i++ )
if( stack[i].lid == drec->r.dir.lid )
return TRUST_UNDEFINED; /* closed (we already visited this lid) */
}
if( !qry_lid_table_flag( ultikey_table, drec->r.dir.lid, NULL ) ) {
/* we are at the end of a path */
TRUST_SEG_LIST tsl;
int i;
stack[depth].trust = TRUST_ULTIMATE;
stack[depth].otrust = TRUST_ULTIMATE;
if( trust_seg_head ) {
/* we can now put copy our current stack to the trust_seg_list */
tsl = m_alloc( sizeof *tsl + (depth+1)*sizeof( TRUST_INFO ) );
for(i=0; i <= depth; i++ )
tsl->path[i] = stack[i];
tsl->pathlen = i;
tsl->next = *trust_seg_head;
*trust_seg_head = tsl;
}
return TRUST_ULTIMATE;
}
/* loop over all user-ids */ /* loop over all user-ids */
if( !all ) /*if( !all ) sigs_seen = new_lid_table();*/
sigs_seen = new_lid_table();
for( rn = drec->r.dir.uidlist; rn; rn = uidrn ) { for( rn = drec->r.dir.uidlist; rn; rn = uidrn ) {
TRUSTREC rec; /* used for uids and sigs */ TRUSTREC rec; /* used for uids and sigs */
ulong sigrn; ulong sigrn;
@ -888,7 +861,36 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
if( (rec.r.uid.uidflags & UIDF_REVOKED) ) if( (rec.r.uid.uidflags & UIDF_REVOKED) )
continue; /* user id has been revoked */ continue; /* user id has been revoked */
/* loop over all signature records */ stack[depth].lid = drec->r.dir.lid;
stack[depth].otrust = drec->r.dir.ownertrust;
stack[depth].trust = 0;
{ int i;
for(i=0; i < depth; i++ )
if( stack[i].lid == drec->r.dir.lid )
return TRUST_UNDEFINED; /* closed (we already visited this lid) */
}
if( !qry_lid_table_flag( ultikey_table, drec->r.dir.lid, NULL ) ) {
/* we are at the end of a path */
TRUST_SEG_LIST tsl;
int i;
stack[depth].trust = TRUST_ULTIMATE;
stack[depth].otrust = TRUST_ULTIMATE;
if( trust_seg_head ) {
/* we can now put copy our current stack to the trust_seg_list */
tsl = m_alloc( sizeof *tsl + (depth+1)*sizeof( TRUST_INFO ) );
for(i=0; i <= depth; i++ )
tsl->path[i] = stack[i];
tsl->pathlen = i;
tsl->next = *trust_seg_head;
*trust_seg_head = tsl;
}
return TRUST_ULTIMATE;
}
/* loop over all signature records of this user id */
for( rn = rec.r.uid.siglist; rn; rn = sigrn ) { for( rn = rec.r.uid.siglist; rn; rn = sigrn ) {
int i; int i;
@ -917,11 +919,11 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
} }
/* visit every signer only once (a signer may have /* visit every signer only once (a signer may have
* signed more than one user ID) */ * signed more than one user ID)
if( sigs_seen && ins_lid_table_item( sigs_seen, * if( sigs_seen && ins_lid_table_item( sigs_seen,
rec.r.sig.sig[i].lid, 0) ) * rec.r.sig.sig[i].lid, 0) )
continue; /* we already have this one */ * continue; we already have this one
*/
read_record( rec.r.sig.sig[i].lid, &tmp, 0 ); read_record( rec.r.sig.sig[i].lid, &tmp, 0 );
if( tmp.rectype != RECTYPE_DIR ) { if( tmp.rectype != RECTYPE_DIR ) {
if( tmp.rectype != RECTYPE_SDIR ) if( tmp.rectype != RECTYPE_SDIR )
@ -945,8 +947,7 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
/* we have signed this key and only in this special case /* we have signed this key and only in this special case
* we assume that this one is fully trusted */ * we assume that this one is fully trusted */
if( !all ) { if( !all ) {
if( sigs_seen ) /*if( sigs_seen ) release_lid_table( sigs_seen );*/
release_lid_table( sigs_seen );
return (stack[depth].trust = TRUST_FULLY); return (stack[depth].trust = TRUST_FULLY);
} }
} }
@ -962,16 +963,14 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
if( fully >= opt.completes_needed if( fully >= opt.completes_needed
|| marginal >= opt.marginals_needed ) { || marginal >= opt.marginals_needed ) {
if( !all ) { if( !all ) {
if( sigs_seen ) /*if( sigs_seen ) release_lid_table( sigs_seen );*/
release_lid_table( sigs_seen );
return (stack[depth].trust = TRUST_FULLY); return (stack[depth].trust = TRUST_FULLY);
} }
} }
} }
} }
} }
if( sigs_seen ) /*if( sigs_seen ) release_lid_table( sigs_seen ); */
release_lid_table( sigs_seen );
if( all && ( fully >= opt.completes_needed if( all && ( fully >= opt.completes_needed
|| marginal >= opt.marginals_needed ) ) { || marginal >= opt.marginals_needed ) ) {
return (stack[depth].trust = TRUST_FULLY ); return (stack[depth].trust = TRUST_FULLY );
@ -983,6 +982,145 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
} }
typedef struct {
ulong lid;
ulong uid;
} CERT_ITEM;
/* structure to hold certification chains. Item[nitems-1] is the
* ultimateley trusted key, item[0] is the key which
* is introduced, indices [1,(nitems-2)] are all introducers.
*/
typedef struct cert_chain *CERT_CHAIN;
struct cert_chain {
CERT_CHAIN next;
int dups;
int nitems;
CERT_ITEM items[1];
};
/****************
* Copy all items to the set SET_HEAD in a way that the requirements
* of a CERT_CHAIN are met.
*/
static void
add_cert_items_to_set( CERT_CHAIN *set_head, CERT_ITEM *items, int nitems )
{
CERT_CHAIN ac;
int i;
ac = m_alloc_clear( sizeof *ac + (nitems-1)*sizeof(CERT_ITEM) );
ac->nitems = nitems;
for(i=0; i < nitems; i++ )
ac->items[i] = items[i];
ac->next = *set_head;
*set_head = ac;
}
/****************
* Find all certification paths of a given LID.
* Limit the search to MAX_DEPTH. stack is a helper variable which
* should have been allocated with size max_depth, stack[0] should
* be setup to the key we are investigating, so the minimal depth
* we should ever see in this function is 1.
* Returns: -1 max_depth reached
* 0 no paths found
* 1 ultimately trusted key found
* certchain_set must be a valid set or point to NULL; this function
* may modifiy it.
*/
static int
find_cert_chain( ulong lid, int depth, int max_depth,
CERT_ITEM *stack, CERT_CHAIN *cert_chain_set )
{
TRUSTREC dirrec;
TRUSTREC uidrec;
ulong uidrno;
if( depth >= max_depth )
return -1;
stack[depth].lid = lid;
stack[depth].uid = 0;
if( !qry_lid_table_flag( ultikey_table, lid, NULL ) ) {
/* this is an ultimately trusted key;
* which means that we have found the end of the chain:
* copy the chain to the set */
add_cert_items_to_set( cert_chain_set, stack, depth+1 );
return 1;
}
read_record( lid, &dirrec, 0 );
if( dirrec.rectype != RECTYPE_DIR ) {
if( dirrec.rectype != RECTYPE_SDIR )
log_debug("lid %lu, has rectype %d"
" - skipped\n", lid, dirrec.rectype );
return 0;
}
/* Performance hint: add stuff to ignore this one when the
* assigned validity of the key is bad */
/* loop over all user ids */
for( uidrno = dirrec.r.dir.uidlist; uidrno; uidrno = uidrec.r.uid.next ) {
TRUSTREC sigrec;
ulong sigrno;
stack[depth].uid = uidrno;
read_record( uidrno, &uidrec, RECTYPE_UID );
if( !(uidrec.r.uid.uidflags & UIDF_CHECKED) )
continue; /* user id has not been checked */
if( !(uidrec.r.uid.uidflags & UIDF_VALID) )
continue; /* user id is not valid */
if( (uidrec.r.uid.uidflags & UIDF_REVOKED) )
continue; /* user id has been revoked */
/* loop over all signature records */
for(sigrno=uidrec.r.uid.siglist; sigrno; sigrno = sigrec.r.sig.next ) {
int i, j;
read_record( sigrno, &sigrec, RECTYPE_SIG );
for(i=0; i < SIGS_PER_RECORD; i++ ) {
if( !sigrec.r.sig.sig[i].lid )
continue; /* skip deleted sigs */
if( !(sigrec.r.sig.sig[i].flag & SIGF_CHECKED) )
continue; /* skip unchecked signatures */
if( !(sigrec.r.sig.sig[i].flag & SIGF_VALID) )
continue; /* skip invalid signatures */
if( (sigrec.r.sig.sig[i].flag & SIGF_EXPIRED) )
continue; /* skip expired signatures */
if( (sigrec.r.sig.sig[i].flag & SIGF_REVOKED) )
continue; /* skip revoked signatures */
for(j=0; j < depth; j++ ) {
if( stack[j].lid == sigrec.r.sig.sig[i].lid )
break;
}
if( j < depth )
continue; /* avoid cycles as soon as possible */
if( find_cert_chain( sigrec.r.sig.sig[i].lid,
depth+1, max_depth,
stack, cert_chain_set ) > 0 ) {
/* ultimately trusted key found:
* no need to check more signatures of this uid */
sigrec.r.sig.next = 0;
break;
}
}
} /* end loop over sig recs */
} /* end loop over user ids */
return 0;
}
/**************** /****************
* Given the directory record of a key, check whether we can * Given the directory record of a key, check whether we can
* find a path to an ultimately trusted key. We do this by * find a path to an ultimately trusted key. We do this by
@ -1337,6 +1475,7 @@ void
list_trust_path( const char *username ) list_trust_path( const char *username )
{ {
int rc; int rc;
ulong lid;
TRUSTREC rec; TRUSTREC rec;
TRUST_INFO *tmppath; TRUST_INFO *tmppath;
TRUST_SEG_LIST trust_seg_list, tsl, tsl2; TRUST_SEG_LIST trust_seg_list, tsl, tsl2;
@ -1357,8 +1496,10 @@ list_trust_path( const char *username )
assert( pk->local_id ); assert( pk->local_id );
} }
} }
lid = pk->local_id;
free_public_key( pk ); free_public_key( pk );
#if 0
/* collect the paths */ /* collect the paths */
tmppath = m_alloc_clear( (opt.max_cert_depth+1)* sizeof *tmppath ); tmppath = m_alloc_clear( (opt.max_cert_depth+1)* sizeof *tmppath );
trust_seg_list = NULL; trust_seg_list = NULL;
@ -1378,6 +1519,26 @@ list_trust_path( const char *username )
m_free( tsl ); m_free( tsl );
} }
trust_seg_list = NULL; trust_seg_list = NULL;
#else /* test code */
{
CERT_ITEM *stack;
CERT_CHAIN chains, r;
int i;
chains = NULL;
stack = m_alloc_clear( (opt.max_cert_depth+1)* sizeof *stack );
find_cert_chain( lid, 0, opt.max_cert_depth, stack, &chains);
m_free( stack );
/* dump chains */
for(r=chains; r ; r = r->next ) {
printf("chain:" );
for(i=0; i < r->nitems; i++ )
printf(" %4lu/%-4lu", r->items[i].lid, r->items[i].uid );
putchar('\n');
}
}
#endif
} }
@ -2719,15 +2880,17 @@ upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
continue; /* skip deleted sigs */ continue; /* skip deleted sigs */
} }
if( rec.r.sig.sig[i].lid == pk_lid ) { if( rec.r.sig.sig[i].lid == pk_lid ) {
#if 0 /* must take uid into account */
if( found_sig ) { if( found_sig ) {
log_info( "sig %08lX.%lu/%02X%02X/%08lX: %s\n", log_info( "sig %08lX.%lu/%02X%02X/%08lX: %s\n",
(ulong)keyid[1], lid, uidhash[18], (ulong)keyid[1], lid, uidhash[18],
uidhash[19], (ulong)sig->keyid[1], uidhash[19], (ulong)sig->keyid[1],
_("Duplicated certificate - deleted") ); _("duplicated certificate - deleted") );
rec.r.sig.sig[i].lid = 0; rec.r.sig.sig[i].lid = 0;
rec.dirty = 1; rec.dirty = 1;
continue; continue;
} }
#endif
found_sig = 1; found_sig = 1;
} }
if( !recheck && !revoke && (rec.r.sig.sig[i].flag & SIGF_CHECKED) ) if( !recheck && !revoke && (rec.r.sig.sig[i].flag & SIGF_CHECKED) )
@ -2811,7 +2974,7 @@ upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
} }
} }
if( found_sig ) if( found_sig ) /* fixme: uid stuff */
return; return;
/* at this point, we have verified, that the signature is not in /* at this point, we have verified, that the signature is not in

View File

@ -1,3 +1,8 @@
Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* cipher.h (CIPHER_ALGO_TWOFISH): Chnaged ID to 10 and renamed
the old experimenatl algorithm to xx_OLD.
Thu Jan 7 18:00:58 CET 1999 Werner Koch <wk@isil.d.shuttle.de> Thu Jan 7 18:00:58 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* cipher.h (MD_BUFFER_SIZE): Removed. * cipher.h (MD_BUFFER_SIZE): Removed.

View File

@ -33,9 +33,10 @@
#define CIPHER_ALGO_BLOWFISH 4 /* blowfish 128 bit key */ #define CIPHER_ALGO_BLOWFISH 4 /* blowfish 128 bit key */
#define CIPHER_ALGO_SAFER_SK128 5 #define CIPHER_ALGO_SAFER_SK128 5
#define CIPHER_ALGO_DES_SK 6 #define CIPHER_ALGO_DES_SK 6
#define CIPHER_ALGO_TWOFISH 10 /* twofish 256 bit */
#define CIPHER_ALGO_BLOWFISH160 42 /* blowfish 160 bit key (not in OpenPGP)*/ #define CIPHER_ALGO_BLOWFISH160 42 /* blowfish 160 bit key (not in OpenPGP)*/
#define CIPHER_ALGO_SKIPJACK 101 /* experimental: skipjack */ #define CIPHER_ALGO_SKIPJACK 101 /* experimental: skipjack */
#define CIPHER_ALGO_TWOFISH 102 /* experimental: twofish 128 bit */ #define CIPHER_ALGO_TWOFISH_OLD 102 /* experimental: twofish 128 bit */
#define CIPHER_ALGO_DUMMY 110 /* no encryption at all */ #define CIPHER_ALGO_DUMMY 110 /* no encryption at all */
#define PUBKEY_ALGO_RSA 1 #define PUBKEY_ALGO_RSA 1
@ -63,11 +64,9 @@ typedef struct {
byte key[24]; /* this is the largest used keylen (3des) */ byte key[24]; /* this is the largest used keylen (3des) */
} DEK; } DEK;
struct cipher_handle_s;
typedef struct cipher_handle_s *CIPHER_HANDLE; typedef struct cipher_handle_s *CIPHER_HANDLE;
#ifndef DEFINES_CIPHER_HANDLE
struct cipher_handle_s { char does_not_matter[1]; };
#endif
#define CIPHER_MODE_ECB 1 #define CIPHER_MODE_ECB 1
#define CIPHER_MODE_CFB 2 #define CIPHER_MODE_CFB 2
@ -75,6 +74,8 @@ struct cipher_handle_s { char does_not_matter[1]; };
#define CIPHER_MODE_AUTO_CFB 4 #define CIPHER_MODE_AUTO_CFB 4
#define CIPHER_MODE_DUMMY 5 /* used with algo DUMMY for no encryption */ #define CIPHER_MODE_DUMMY 5 /* used with algo DUMMY for no encryption */
struct md_digest_list_s;
typedef struct { typedef struct {
int secure; int secure;
FILE *debug; FILE *debug;
@ -85,12 +86,6 @@ typedef struct {
} *MD_HANDLE; } *MD_HANDLE;
#ifndef DEFINES_MD_HANDLE /* not really the handle but the algorithm list */
struct md_digest_list_s { char does_not_matter[1]; };
#endif
int g10c_debug_mode; int g10c_debug_mode;
int g10_opt_verbose; int g10_opt_verbose;

View File

@ -127,10 +127,12 @@ const char *strusage( int level );
/*-- dotlock.c --*/ /*-- dotlock.c --*/
const char *make_dotlock( const char *file_to_lock, long timeout ); struct dotlock_handle;
int release_dotlock( const char *lockfile ); typedef struct dotlock_handle *DOTLOCK;
DOTLOCK create_dotlock( const char *file_to_lock );
int make_dotlock( DOTLOCK h, long timeout );
int release_dotlock( DOTLOCK h );
/*-- fileutil.c --*/ /*-- fileutil.c --*/

View File

@ -1,3 +1,7 @@
Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* pl.po: New version.
Wed Jan 20 21:40:21 CET 1999 Werner Koch <wk@isil.d.shuttle.de> Wed Jan 20 21:40:21 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* es_ES.po: Import of new version. * es_ES.po: Import of new version.

1051
po/pl.po

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,7 @@
Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* config.sub, config.guess: Support i386-emx-os2
Sun Jan 17 11:04:33 CET 1999 Werner Koch <wk@isil.d.shuttle.de> Sun Jan 17 11:04:33 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* autogen.sh: Now checks for installed gettext * autogen.sh: Now checks for installed gettext

View File

@ -708,6 +708,10 @@ main ()
printf ("i860-alliant-bsd\n"); exit (0); printf ("i860-alliant-bsd\n"); exit (0);
#endif #endif
#ifdef __EMX__
printf ("i386-emx-os2"); exit(0);
#endif
exit (1); exit (1);
} }
EOF EOF

6
scripts/config.sub vendored
View File

@ -282,6 +282,9 @@ case $basic_machine in
atarist) atarist)
basic_machine=m68k-atari basic_machine=m68k-atari
;; ;;
emx)
basic_machine=i386-emx
;;
aux) aux)
basic_machine=m68k-apple basic_machine=m68k-apple
os=-aux os=-aux
@ -971,6 +974,9 @@ case $os in
-mint) -mint)
os=-mint os=-mint
;; ;;
-os2)
os=-os2
;;
-none) -none)
;; ;;
*) *)

View File

@ -18,6 +18,10 @@ fix_it () {
EOF EOF
cvs -Q checkout -p gnupg/NEWS >>$dir/NEWS cvs -Q checkout -p gnupg/NEWS >>$dir/NEWS
here=`pwd`
cd $dir
ln -sf gnupg.html index.html
cd $here
} }

View File

@ -22,7 +22,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef __MINGW32__ #ifdef HAVE_DOSISH_SYSTEM
#include <io.h> #include <io.h>
#include <fcntl.h> #include <fcntl.h>
#endif #endif
@ -67,7 +67,7 @@ main(int argc, char **argv)
int n, size=4096; int n, size=4096;
int algo; int algo;
#ifdef __MINGW32__ #ifdef HAVE_DOSISH_SYSTEM
setmode( fileno(stdin), O_BINARY ); setmode( fileno(stdin), O_BINARY );
setmode( fileno(stdout), O_BINARY ); setmode( fileno(stdout), O_BINARY );
#endif #endif

View File

@ -19,10 +19,10 @@
#include "ttyio.h" #include "ttyio.h"
#include "i18n.h" #include "i18n.h"
#ifdef __MINGW32__ #ifdef HAVE_DOSISH_SYSTEM
int main( int argc, char **argv ) int main( int argc, char **argv )
{ {
fprintf(stderr, "Sorry, not yet available for Windoze\n"); fprintf(stderr, "Sorry, not yet available for DOSish systems\n");
exit(1); exit(1);
} }
#else #else
@ -193,4 +193,4 @@ main(int argc, char **argv)
} }
#endif /* !__MINGW32__ */ #endif

View File

@ -1,3 +1,10 @@
Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* dotlock.c (remove_lockfiles): Add cleanup function.
(make_dotlock): Add deadlock check.
* secmem.c (secmem_malloc): Changed error message.
Wed Jan 20 21:40:21 CET 1999 Werner Koch <wk@isil.d.shuttle.de> Wed Jan 20 21:40:21 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* http.c (http_wait_response): Moved the shutdown behind the dup * http.c (http_wait_response): Moved the shutdown behind the dup

View File

@ -35,37 +35,56 @@
#include "util.h" #include "util.h"
#include "memory.h" #include "memory.h"
struct dotlock_handle {
struct dotlock_handle *next;
char *tname; /* name of lockfile template */
char *lockname; /* name of the real lockfile */
int locked; /* lock status */
};
static DOTLOCK all_lockfiles;
static int read_lockfile( const char *name ); static int read_lockfile( const char *name );
static void remove_lockfiles(void);
/**************** /****************
* Create a lockfile with the given name. A TIMEOUT of 0 * Create a lockfile with the given name and return an object of
* returns immediately, -1 waits forever (hopefully not), other * type DOTLOCK which may be used later to actually do the lock.
* values are timeouts in milliseconds. * A cleanup routine gets installed to cleanup left over locks
* Returns: a char pointer used as handle for release lock * or other files used together with the lockmechanism.
* or NULL in case of an error. * Althoug the function is called dotlock, this does not necessarily
* mean that real lockfiles are used - the function may decide to
* use fcntl locking. Calling the function with NULL only install
* the atexit handler and maybe used to assure that the cleanup
* is called after all other atexit handlers.
* *
* Notes: This function creates a lock file in the same directory * Notes: This function creates a lock file in the same directory
* as file_to_lock with the name "file_to_lock.lock" * as file_to_lock with the name "file_to_lock.lock"
* A temporary file ".#lk.<hostname>.pid[.threadid] is used. * A temporary file ".#lk.<hostname>.pid[.threadid] is used.
* This function does nothing for Windoze. * This function does nothing for Windoze.
*/ */
const char * DOTLOCK
make_dotlock( const char *file_to_lock, long timeout ) create_dotlock( const char *file_to_lock )
{ {
int fd=-1, pid; static int initialized;
DOTLOCK h;
int fd = -1;
char pidstr[16]; char pidstr[16];
const char *handle = NULL;
char *lockname = NULL;
char *tname = NULL;
int have_tfile = 0;
struct utsname uts; struct utsname uts;
const char *nodename; const char *nodename;
const char *dirpart; const char *dirpart;
int dirpartlen; int dirpartlen;
const char *maybe_dead="";
int backoff=0;
if( !initialized ) {
atexit( remove_lockfiles );
initialized = 1;
}
if( !file_to_lock )
return NULL;
h = m_alloc_clear( sizeof *h );
#ifndef HAVE_DOSISH_SYSTEM
sprintf( pidstr, "%10d\n", getpid() ); sprintf( pidstr, "%10d\n", getpid() );
/* fixme: add the hostname to the second line (FQDN or IP addr?) */ /* fixme: add the hostname to the second line (FQDN or IP addr?) */
@ -84,131 +103,180 @@ make_dotlock( const char *file_to_lock, long timeout )
dirpart = file_to_lock; dirpart = file_to_lock;
} }
#ifdef _THREAD_SAFE #ifdef _REENTRANT
tname = m_alloc( dirpartlen + 6 + strlen(nodename) + 11+ 20 ); /* fixme: aquire mutex on all_lockfiles */
sprintf( tname, "%.*s/.#lk.%s.%d.%p",
dirpartlen, dirpart, nodename, getpid(), &pid );
#else
tname = m_alloc( dirpartlen + 6 + strlen(nodename) + 11 );
sprintf( tname, "%.*s/.#lk.%s.%d",
dirpartlen, dirpart, nodename, getpid() );
#endif #endif
h->next = all_lockfiles;
all_lockfiles = h;
h->tname = m_alloc( dirpartlen + 6+30+ strlen(nodename) + 11 );
sprintf( h->tname, "%.*s/.#lk%p.%s.%d",
dirpartlen, dirpart, h, nodename, (int)getpid() );
do { do {
errno = 0; errno = 0;
fd = open( tname, O_WRONLY|O_CREAT|O_EXCL, fd = open( h->tname, O_WRONLY|O_CREAT|O_EXCL,
S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR ); S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
} while( fd == -1 && errno == EINTR ); } while( fd == -1 && errno == EINTR );
if( fd == -1 ) { if( fd == -1 ) {
log_error( "failed to create temporary file `%s': %s\n", log_error( "failed to create temporary file `%s': %s\n",
tname, strerror(errno)); h->tname, strerror(errno));
goto leave; m_free(h->tname);
m_free(h);
return NULL;
} }
have_tfile = 1;
if( write(fd, pidstr, 11 ) != 11 ) { if( write(fd, pidstr, 11 ) != 11 ) {
log_fatal( "error writing to `%s': %s\n", tname, strerror(errno) ); all_lockfiles = h->next;
goto leave; #ifdef _REENTRANT
/* release mutex */
#endif
log_fatal( "error writing to `%s': %s\n", h->tname, strerror(errno) );
close(fd);
unlink(h->tname);
m_free(h->tname);
m_free(h);
return NULL;
} }
if( close(fd) ) { if( close(fd) ) {
log_error( "error closing `%s': %s\n", tname, strerror(errno)); all_lockfiles = h->next;
goto leave; #ifdef _REENTRANT
/* release mutex */
#endif
log_error( "error closing `%s': %s\n", h->tname, strerror(errno));
unlink(h->tname);
m_free(h->tname);
m_free(h);
return NULL;
} }
fd = -1;
lockname = m_alloc( strlen(file_to_lock) + 6 ); #ifdef _REENTRANT
strcpy(stpcpy(lockname, file_to_lock), ".lock"); /* release mutex */
#endif
#endif /* !HAVE_DOSISH_SYSTEM */
h->lockname = m_alloc( strlen(file_to_lock) + 6 );
strcpy(stpcpy(h->lockname, file_to_lock), ".lock");
return h;
}
retry: static int
if( !link(tname, lockname) ) {/* fixme: better use stat to check the link count */ maybe_deadlock( DOTLOCK h )
handle = lockname; {
lockname = NULL; DOTLOCK r;
for( r=all_lockfiles; r; r = r->next ) {
if( r != h && r->locked )
return 1;
} }
else if( errno == EEXIST ) { return 0;
if( (pid = read_lockfile(lockname)) == -1 ) { }
if( errno == ENOENT ) {
log_info( "lockfile disappeared\n"); /****************
goto retry; * Do a lock on H. A TIMEOUT of 0 returns immediately,
* -1 waits forever (hopefully not), other
* values are timeouts in milliseconds.
* Returns: 0 on success
*/
int
make_dotlock( DOTLOCK h, long timeout )
{
#ifdef HAVE_DOSISH_SYSTEM
return 0;
#else
int pid;
const char *maybe_dead="";
int backoff=0;
if( h->locked ) {
log_debug("oops, `%s' is already locked\n", h->lockname );
return 0;
}
for(;;) {
if( !link(h->tname, h->lockname) ) {
/* fixme: better use stat to check the link count */
h->locked = 1;
return 0; /* okay */
}
if( errno != EEXIST ) {
log_error( "lock not made: link() failed: %s\n", strerror(errno) );
return -1;
}
if( (pid = read_lockfile(h->lockname)) == -1 ) {
if( errno != ENOENT ) {
log_info("cannot read lockfile\n");
return -1;
} }
log_info("cannot read lockfile\n"); log_info( "lockfile disappeared\n");
continue;
} }
else if( pid == getpid() ) { else if( pid == getpid() ) {
log_info( "Oops: lock already hold by us\n"); log_info( "Oops: lock already hold by us\n");
handle = lockname; h->locked = 1;
lockname = NULL; return 0; /* okay */
} }
else if( kill(pid, 0) && errno == ESRCH ) { else if( kill(pid, 0) && errno == ESRCH ) {
maybe_dead = " - probably dead"; maybe_dead = " - probably dead";
#if 0 /* we should not do this without checking the permissions */ #if 0 /* we should not do this without checking the permissions */
/* and the hostname */ /* and the hostname */
log_info( "removing stale lockfile (created by %d)", pid ); log_info( "removing stale lockfile (created by %d)", pid );
remove( lockname );
goto retry;
#endif #endif
} }
if( timeout == -1 ) { if( timeout == -1 ) {
struct timeval tv; struct timeval tv;
log_info( "waiting for lock (hold by %d%s) ...\n", pid, maybe_dead ); log_info( "waiting for lock (hold by %d%s) %s...\n",
pid, maybe_dead, maybe_deadlock(h)? "(deadlock?) ":"");
/* can't use sleep, cause signals may be blocked */ /* can't use sleep, cause signals may be blocked */
tv.tv_sec = 1 + backoff; tv.tv_sec = 1 + backoff;
tv.tv_usec = 0; tv.tv_usec = 0;
select(0, NULL, NULL, NULL, &tv); select(0, NULL, NULL, NULL, &tv);
if( backoff < 10 ) if( backoff < 10 )
backoff++ ; backoff++ ;
goto retry;
} }
/* fixme: implement timeouts */ else
return -1;
} }
else /*not reached */
log_error( "lock not made: link() failed: %s\n", strerror(errno) ); #endif /* !HAVE_DOSISH_SYSTEM */
leave:
if( fd != -1 )
close(fd);
if( have_tfile )
remove(tname);
m_free(tname);
m_free(lockname);
return handle;
} }
/****************
* Create a lockfile for a existing file
* Returns: a char pointer used as handle for release lock
* or NULL in case of an error.
*
* Notes: This function creates a lock file in the same directory
* as file_to_lock with the name "lock.<inode-no>"
*
* int
* make_inodelock( const char *file_to_lock )
*
*/
/**************** /****************
* release a lock * release a lock
* Returns: 0 := success * Returns: 0 := success
*/ */
int int
release_dotlock( const char *lockfile ) release_dotlock( DOTLOCK h )
{ {
int pid = read_lockfile( lockfile ); #ifdef HAVE_DOSISH_SYSTEM
return 0;
#else
int pid;
if( !h->locked ) {
log_debug("oops, `%s' is not locked\n", h->lockname );
return 0;
}
pid = read_lockfile( h->lockname );
if( pid == -1 ) { if( pid == -1 ) {
log_error( "release_dotlock: lockfile error"); log_error( "release_dotlock: lockfile error\n");
return -1; return -1;
} }
if( pid != getpid() ) { if( pid != getpid() ) {
log_error( "release_dotlock: not our lock (pid=%d)", pid); log_error( "release_dotlock: not our lock (pid=%d)\n", pid);
return -1; return -1;
} }
if( remove( lockfile ) ) { if( unlink( h->lockname ) ) {
log_error( "release_dotlock: error removing lockfile `%s'", log_error( "release_dotlock: error removing lockfile `%s'",
lockfile); h->lockname);
return -1; return -1;
} }
m_free( (char*)lockfile ); /* fixme: check that the link count is now 1 */
h->locked = 0;
return 0; return 0;
#endif /* !HAVE_DOSISH_SYSTEM */
} }
@ -218,6 +286,9 @@ release_dotlock( const char *lockfile )
static int static int
read_lockfile( const char *name ) read_lockfile( const char *name )
{ {
#ifdef HAVE_DOSISH_SYSTEM
return 0;
#else
int fd, pid; int fd, pid;
char pidstr[16]; char pidstr[16];
@ -241,5 +312,29 @@ read_lockfile( const char *name )
return -1; return -1;
} }
return pid; return pid;
#endif
}
static void
remove_lockfiles()
{
#ifndef HAVE_DOSISH_SYSTEM
DOTLOCK h, h2;
h = all_lockfiles;
all_lockfiles = NULL;
while( h ) {
h2 = h->next;
if( h->locked )
unlink( h->lockname );
unlink(h->tname);
m_free(h->tname);
m_free(h->lockname);
m_free(h);
h = h2;
}
#endif
} }

View File

@ -38,16 +38,16 @@ char *
make_basename(const char *filepath) make_basename(const char *filepath)
{ {
char *p; char *p;
if ( !(p=strrchr(filepath, '/')) ) if ( !(p=strrchr(filepath, '/')) )
#ifdef __MINGW32__ #ifdef HAVE_DRIVE_LETTERS
if ( !(p=strrchr(filepath, '\\')) ) if ( !(p=strrchr(filepath, '\\')) )
if ( !(p=strrchr(filepath, ':')) ) if ( !(p=strrchr(filepath, ':')) )
#endif #endif
{ {
return m_strdup(filepath); return m_strdup(filepath);
} }
return m_strdup(p+1); return m_strdup(p+1);
} }
@ -65,21 +65,21 @@ make_dirname(const char *filepath)
char *dirname; char *dirname;
int dirname_length; int dirname_length;
char *p; char *p;
if ( !(p=strrchr(filepath, '/')) ) if ( !(p=strrchr(filepath, '/')) )
#ifdef __MINGW32__ #ifdef HAVE_DRIVE_LETTERS
if ( !(p=strrchr(filepath, '\\')) ) if ( !(p=strrchr(filepath, '\\')) )
if ( !(p=strrchr(filepath, ':')) ) if ( !(p=strrchr(filepath, ':')) )
#endif #endif
{ {
return m_strdup("."); return m_strdup(".");
} }
dirname_length = p-filepath; dirname_length = p-filepath;
dirname = m_alloc(dirname_length+1); dirname = m_alloc(dirname_length+1);
strncpy(dirname, filepath, dirname_length); strncpy(dirname, filepath, dirname_length);
dirname[dirname_length] = 0; dirname[dirname_length] = 0;
return dirname; return dirname;
} }
@ -126,7 +126,7 @@ compare_filenames( const char *a, const char *b )
/* ? check whether this is an absolute filename and /* ? check whether this is an absolute filename and
* resolve symlinks? * resolve symlinks?
*/ */
#ifdef __MINGW32__ #ifdef HAVE_DRIVE_LETTERS
return stricmp(a,b); return stricmp(a,b);
#else #else
return strcmp(a,b); return strcmp(a,b);

View File

@ -126,8 +126,11 @@ file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
*(char**)buf = "file_filter"; *(char**)buf = "file_filter";
} }
else if( control == IOBUFCTRL_FREE ) { else if( control == IOBUFCTRL_FREE ) {
if( fp != stdin && fp != stdout ) if( fp != stdin && fp != stdout ) {
if( DBG_IOBUF )
log_debug("%s: close fd %d\n", a->fname, fileno(fp) );
fclose(fp); fclose(fp);
}
fp = NULL; fp = NULL;
m_free(a); /* we can free our context now */ m_free(a); /* we can free our context now */
} }
@ -545,7 +548,8 @@ iobuf_open( const char *fname )
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len ); file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len ); file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
if( DBG_IOBUF ) if( DBG_IOBUF )
log_debug("iobuf-%d.%d: open `%s'\n", a->no, a->subno, fname ); log_debug("iobuf-%d.%d: open `%s' fd=%d\n",
a->no, a->subno, fname, fileno(fcx->fp) );
return a; return a;
} }

View File

@ -217,7 +217,7 @@ void
secmem_init( size_t n ) secmem_init( size_t n )
{ {
if( !n ) { if( !n ) {
#ifndef __MINGW32__ #ifndef HAVE_DOSISH_SYSTEM
uid_t uid; uid_t uid;
disable_secmem=1; disable_secmem=1;
@ -245,8 +245,12 @@ secmem_malloc( size_t size )
MEMBLOCK *mb, *mb2; MEMBLOCK *mb, *mb2;
int compressed=0; int compressed=0;
if( !pool_okay ) if( !pool_okay ) {
log_bug("secmem not initialized\n"); log_info(
_("operation is not possible without initialized secure memory\n"));
log_info(_("(you may have used the wrong program for this task)\n"));
exit(2);
}
if( show_warning && !suspend_warning ) { if( show_warning && !suspend_warning ) {
show_warning = 0; show_warning = 0;
print_warn(); print_warn();

View File

@ -105,6 +105,8 @@ init_ttyfp()
SetConsoleMode(con.in, DEF_INPMODE ); SetConsoleMode(con.in, DEF_INPMODE );
SetConsoleMode(con.out, DEF_OUTMODE ); SetConsoleMode(con.out, DEF_OUTMODE );
#elif defined(__EMX__)
ttyfp = stdout; /* Fixme: replace by the real functions: see wklib */
#else #else
ttyfp = fopen("/dev/tty", "r+"); ttyfp = fopen("/dev/tty", "r+");
if( !ttyfp ) if( !ttyfp )