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>
* 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)
--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
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
option "--debug 128" displays a memory statistic after
the program run.
@ -55,8 +55,8 @@ Don't forget to delete "config.cache" and run "./config.status --recheck".
The Random Device
=================
Random devices are available in Linux, FreeBSD and OpenBSD.
The device files may not exist on your system, please check this
and create them if needed.
The random device files may not exist on your system, please check whether
they do and create them if needed.
The Linux files should look like this:
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/urandom c 2 4
Unices without a random devices must use another entropy collector
which is called rndunix and available as an extension module. You
Unices without a random devices must use another entropy collector. One
entropy collector called rndunix and available as an extension module. You
should put this in your ~/.gnupg/options file:
===8<====================
load-extension rndunix
===>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
generator - It should work reliable but you should check whether
it produces good output for your kind of Unix. There are some debug
generator - It should work reliably but you should check whether
it produces good output for your version of Unix. There are some debug
options to help you (see cipher/rndunix.c).
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.
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'
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
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The file `configure.in' is used by the program `autoconf' to create
`configure'. You only need `configure.in' if you want to change it or
regenerate `configure' using a newer version of `autoconf'.
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
`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.
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:
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
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
You can compile the package for more than one kind of computer at the same
time by placing the object files for each architecture in their own
directory. To do this, you must use a version of `make', such as GNU `make',
that supports the `VPATH' variable. `cd' to the directory where you want the
object files and executables to go and run the `configure' script.
`configure' automatically checks for the source code in the directory that
`configure' is in and in `..'.
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

View File

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

367
README
View File

@ -1,19 +1,19 @@
-----BEGIN PGP SIGNED MESSAGE-----
GnuPG - The GNU Privacy Guard
-------------------------------
Version 0.9
GnuPG - The GNU Privacy Guard
-------------------------------
Version 0.9
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
to fix all remaining serious bugs. As soon as version 1.0 is out,
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,
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
also supported but not as good tested as those Freenix ones.
Please verify the tar file; there is a PGP2 and a GnuPG/PGP5
signature available. My PGP2 key is well known and published in
also supported but are not as well tested as the Free Unices.
Please verify the tar file with the PGP2 or GnuPG/PGP5
signatures provided. My PGP2 key is well known and published in
the "Global Trust Register for 1998", ISBN 0-9532397-0-5.
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>"
"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
verify new releases. Because you verified this README file and
_checked_that_it_is_really_my PGP2 key 0C9857A5, you can be sure
that the above fingerprints are correct.
You may want add my new DSA key to your GnuPG pubring and use it in
the future to verify new releases. Because you verified this README
file and _checked_that_it_is_really_my PGP2 key 0C9857A5, you can be
sure that the above fingerprints are correct.
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".
This mailing list is a closed one (only subscribers are allowed
to post) to avoid misuse by folks who don't know the Netiquette
and trash your mailspool with commercial junk.
This mailing list is closed (only subscribers are allowed to post)
to avoid misuse by folks who don't know the Netiquette and trash
your mailspool with commercial junk.
See the file COPYING for copyright and warranty information.
GnuPG is in compliance with RFC2440 (OpenPGP), see doc/OpenPGP for
details.
Due to the fact that GnuPG does not use use any patented algorithm,
it cannot be compatible with PGP2 versions; PGP 2.x does only use
IDEA (which is patented worldwide) and RSA (which is patented in
the United States until Sep 20, 2000).
Because GnuPG does not use use any patented algorithm it cannot be
compatible with PGP2 versions. PGP 2.x uses only IDEA (which is
patented worldwide) and RSA (which is patented in the United States
until Sep 20, 2000).
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 depreciated (Please note that the GnuPG implementation of ElGamal
signatures is *not* insecure). Symmetric algorithms are: 3DES,
Blowfish and CAST5 (Twofish will come soon), available digest
algorithms are MD5, RIPEMD160, SHA1 and TIGER/192.
is still available, but because of the larger size of such
signatures it is deprecated (Please note that the GnuPG
implementation of ElGamal signatures is *not* insecure). Symmetric
algorithms are: 3DES, Blowfish, and CAST5 (Twofish will come soon).
Digest algorithms available are MD5, RIPEMD160, SHA1, and TIGER/192.
Installation
@ -61,7 +61,7 @@
Here is a quick summary:
1) "./configure"
1) "./configure"
2) "make"
@ -69,24 +69,25 @@
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
-----
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
of cryptography. GnuPG is only the technical tool to do it and
the security highly depends on that YOU KNOW WHAT YOU ARE DOING.
Introduction
------------
This is a brief overview how to use GnuPG - it is strongly suggested
that you read the manual^H^H^H more information about the use of
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)
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
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
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
remember. Don't make the passphrase too long because you have 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
When you are asked for a passphrase use a good one which you can
easy remember. Don't make the passphrase too long because you have
to type it for every decryption or signing; but, - AND THIS IS VERY
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
passphrase is used to protect this secret key in case someone was
able to get access to your secret keyring. A good way to select
a passphrase is to figure out a short nonsense sentence which makes
some sense for you and modify it by inserting extra spaces, non-letters
and changing the case of some characters - this is really easy to
remember especially if you associate some pictures with it.
passphrase that protects it when someone gains access to your secret
keyring. A good way to select a passphrase is to figure out a short
nonsense sentence which makes some sense for you and modify it by
inserting extra spaces, non-letters and changing the case of some
characters - this is really easy to remember especially if you
associate some pictures with it.
Then you should create a revocation certificate in case someone
gets knowledge of your secret key or you forgot your passphrase:
Next, you should create a revocation certificate in case someone
gets knowledge of your secret key or you forgot your passphrase
gpg --gen-revoke your_user_id
gpg --gen-revoke your_user_id
Run this command and store it away; output is always ASCII armored,
so that you can print it and (hopefully never) re-create it if
your electronic media fails.
Run this command and store the revocation certificate away. The output
is always ASCII armored, so that you can print it and (hopefully
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
attached.
This creates a file "file.gpg" which is compressed and has a
signature attached.
gpg -sa file
gpg -sa file
Same as above, but creates the file.asc which is ascii armored and
and ready for sending by mail. Note: It is better to use your
Same as above, but creates a file "file.asc" which is ASCII armored
and and ready for sending by mail. It is better to use your
mailers features to create signatures (The mailer uses GnuPG to do
this) because the mailer has the ability to MIME encode such
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
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
appropriate message. If the signature is good, you know at least
that the person (or machine) has access to the secret key which
corresponds to the published public key.
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
can also run as a filter, so that you can pipe data to verify
trough it:
create a new file that is identical to the original. gpg can also
run as a filter, so that you can pipe data to verify 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.
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"
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.
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.
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"
GnuPG has some options to help you publish public keys; this is
called "exporting" a key:
GnuPG has some options to help you publish public keys. This is
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)
to all-my-keys. You may then mail "all-my-keys" as an MIME attachment
to someone else or put it on an FTP server. To export only some
user IDs, you give them as arguments on the command line.
exports all the keys in the keyring and writes them (in a binary
format) to "all-my-keys". You may then mail "all-my-keys" as an
MIME attachment to someone else or put it on an FTP server. To
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
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.
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
keys are updated. Note that GnuPG does not allow keys which
are not self-signed by the user.
keys are updated. Note that GnuPG does not import keys that
are not self-signed.
Because anyone can claim that the public key belongs to her
we must have some way to check that the public key really belongs
Because anyone can claim that a public key belongs to her
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
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
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
sigs or on business cards) which uniquely identify the public
key - two different keys will always have different fingerprints.
It is easy to compare this fingerprint by phone and I suggest
sigs or on business cards) that uniquely identifies the public
key - different keys will always have different fingerprints.
It is easy to compare fingerprints by phone and I suggest
that you print your fingerprint on the back of your business
card.
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
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
act as introducer to you; this is done by signing the keys and
thereby certifying the other keys. If you then trust all the
introducers to correctly sign other keys, you can be be sure that
the other key really belongs to the one who claims so.
If you don't know the owner of the public key you are in trouble.
Suppose however that friend of yours knows someone who knows someone
who has met the owner of the public key at some computer conference.
Suppose that all the people between you and the public key holder
may now act as introducers to you. Introducers signing keys thereby
certify that they know the owner of the keys they sign. If you then
trust all the introducers to have correctly signed other keys, you
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:
1. First check that there is a complete chain
of signed keys from the public key you want to use
and your key and verify each signature.
2. Make sure that you have full trust in the certificates
of all the introduces between the public key holder and
you.
There are 2 steps to validate a key:
1. First check that there is a complete chain
of signed keys from the public key you want to use
and your key and verify each signature.
2. Make sure that you have full trust in the certificates
of all the introduces between the public key holder and
you.
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
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
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
of the chains of certificates, in which this key is used
as an introducer, to validate the target key. Use this if
you don't know the introducer.
of the chains of certificates, in which this key is used
as an introducer, to validate the target key. Use this if
you don't know 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
is the same as with a) but for a) you may later want to
change the value because you got new information about this
introducer.
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
change the value because you got new information about this
introducer.
c) "I trust marginally" - Use this if you assume that the
introducer knows what he is doing. Together with some
other marginally trusted keys, GnuPG validates the target
key then as good.
introducer knows what he is doing. Together with some
other marginally trusted keys, GnuPG validates the target
key then as good.
d) "I fully trust" - Use this if you really know that this
introducer does a good job when certifying other keys.
If all the introducer are of this trust value, GnuPG
normally needs only one chain of signatures to validate
a target key okay. (But this may be adjusted with the help
of some options).
These information are confidential because they give your
personal opinion on the trustworthy of someone else. Therefore
this data is not stored in the keyring but in the "trustdb"
introducer does a good job when certifying other keys.
If all the introducer are of this trust value, GnuPG
normally needs only one chain of signatures to validate
a target key okay. (But this may be adjusted with the help
of some options).
This information is confidential because it gives your personal
opinion on the trustworthiness of someone else. Therefore this data
is not stored in the keyring but in the "trustdb"
(~/.gnupg/trustdb.gpg). Do not assign a high trust value just
because the introducer is a friend of you - decide how far she
understands all the implications of key signatures and you may
want to tell him more about public key cryptography so you
can later change the trust value you assigned.
because the introducer is a friend of yours - decide how well she
understands the implications of key signatures and you may want to
tell her more about public key cryptography so you can later change
the trust value you assigned.
Okay, here is how GnuPG helps you in key management: Most stuff is
done with the --edit-key command:
Okay, here is how GnuPG helps you with key management. Most stuff
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
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
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
follow all the prompts. When you are ready, give the command
"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
"--edit-key".
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
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
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
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
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
to change the user ID later without voiding all the signatures.
@ -310,51 +314,59 @@
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):
"234567C4"
"0F34E556E"
"01347A56A"
"0xAB123456
"234567C4"
"0F34E556E"
"01347A56A"
"0xAB123456
* By a complete keyid:
"234AABBCC34567C4"
"0F323456784E56EAB"
"01AB3FED1347A5612"
"0x234AABBCC34567C4"
"234AABBCC34567C4"
"0F323456784E56EAB"
"01AB3FED1347A5612"
"0x234AABBCC34567C4"
* By a fingerprint:
"1234343434343434C434343434343434"
"123434343434343C3434343434343734349A3434"
"0E12343434343434343434EAB3484343434343434"
"1234343434343434C434343434343434"
"123434343434343C3434343434343734349A3434"
"0E12343434343434343434EAB3484343434343434"
The first one is MD5 the others are ripemd160 or sha1.
* By an exact string:
"=Heinrich Heine <heinrichh@uni-duesseldorf.de>"
"=Heinrich Heine <heinrichh@uni-duesseldorf.de>"
* 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):
"#34"
"#34"
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:
"Heine"
"*Heine"
"Heine"
"*Heine"
The '*' indicates substring search explicitly.
@ -363,7 +375,7 @@
----------
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
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
PGPPASSFD.
@ -375,29 +387,29 @@
-----------
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
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.
Esoteric commands
-----------------
gpg --list-packets datafile
gpg --list-packets datafile
Use this to list the contents of a data file. If the file is encrypted
you are asked for the passphrase, so that GnuPG is able to look at the
inner structure of a encrypted packet. This command should be able
to list all kinds of rfc2440 messages.
inner structure of a encrypted packet. This command should list all
kinds of rfc2440 messages.
gpgm --list-trustdb
gpgm --list-trustdb
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
gpgm --list-trust-path username
gpgm --list-trust-path username
List the possible trust paths for the given username. The length
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
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
closed list - subscribe before posting, see above (~line 33)).
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.
Have fun and remember: Echelon is looking at you kid.
-----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
iQB1AwUBNpyIDR0Z9MEMmFelAQGn4gL+IVlEye5I6LplxdUExsrHQpLV21H0UXFa
/Dl1T/HjrGHj41NeW2evO4Ck2K6Z0TG5jPg9CuJdcJp0siJ8odO7BTLaF3r6gwxF
CA4EXgqhSyE8PXRPS4m4M5I7Ru/bsZrF
=HfE0
iQB1AwUBNr2fPh0Z9MEMmFelAQHqNAL/e7pApR0CGUJ/zuIsjaVhNGPEgKAglcEd
YuVdB+RCN0wq7ZfI0AHU2FdVISRACmSN3xituTTgeiOUsczM40EZ4l1XNfyRF768
fglui6XxEeYHFY7mSQMgzzFWDG0Squx0
=enRo
-----END PGP SIGNATURE-----

9
TODO
View File

@ -8,8 +8,13 @@ Bugs
* 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
----------
* replace gettext by a non exploitable one.
* Check revocation and expire stuff. PLEASE: THIS MUST BE TESTED!
* 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
be working OK so far.
* Use capabilities if available.
Minor Bugs
----------
@ -56,7 +63,7 @@ Nice to have
really make sense?
* change the fake_data stuff to mpi_set_opaque
* How about letting something like 'gpg --version -v', list the
effective options.
effective options. Too much work.
* Stats about used random numbers.

View File

@ -32,6 +32,7 @@
#undef VERSION
#undef PACKAGE
#undef PRINTABLE_OS_NAME
#undef IS_DEVELOPMENT_VERSION
/* Define if your locale.h file contains LC_MESSAGES. */
#undef HAVE_LC_MESSAGES
@ -64,14 +65,6 @@
#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 */
#undef HAVE_DEV_RANDOM
/* and the real names of the random devices */
@ -92,6 +85,11 @@
#undef USE_ONLY_8DOT3
/* defined if we must run on a stupid file system */
#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@

View File

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

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>
* rndunix.c (gather_random): Fix to avoid infinite loop.

View File

@ -1,12 +1,33 @@
## Process this file with automake to produce Makefile.in
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl
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
pkglib_PROGRAMS = @DYNAMIC_CIPHER_MODS@ @DYNAMIC_RANDOM_MODS@
pkglib_PROGRAMS = @DYNAMIC_CIPHER_MODS@
else
pkglib_PROGRAMS =
endif
@ -27,37 +48,41 @@ libcipher_a_SOURCES = cipher.c \
cast5.h \
elgamal.c \
elgamal.h \
md5.c \
md5.h \
primegen.c \
random.h \
random.c \
rand-internal.h \
rmd.h \
rmd160.c \
sha1.h \
sha1.c \
dsa.h \
dsa.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
EXTRA_tiger_SOURCES = tiger.c
EXTRA_twofish_SOURCES = twofish.c
libcipher_a_DEPENDENCIES = @STATIC_CIPHER_OBJS@
libcipher_a_LIBADD = @STATIC_CIPHER_OBJS@
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
`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
`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

View File

@ -37,6 +37,7 @@
#include "types.h"
#include "errors.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
*/
#define DEFINES_CIPHER_HANDLE 1
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
@ -160,6 +158,7 @@ load_cipher_modules()
int any = 0;
if( !initialized ) {
cipher_modules_constructor();
setup_cipher_table(); /* load static modules on the first call */
initialized = 1;
return 1;

View File

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

View File

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

View File

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

View File

@ -34,8 +34,8 @@
#include <string.h>
#include <assert.h>
#include "util.h"
#include "md5.h"
#include "memory.h"
#include "dynload.h"
typedef struct {
@ -338,7 +338,7 @@ md5_read( MD5_CONTEXT *hd )
* Returns: A pointer to string describing the algorithm or NULL if
* the ALGO is invalid.
*/
const char *
static const char *
md5_get_info( int algo, size_t *contextsize,
byte **r_asnoid, int *r_asnlen, int *r_mdlen,
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 */

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 ) {
cipher_modules_constructor();
setup_pubkey_table();
initialized = 1;
return 1;

View File

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

View File

@ -32,16 +32,4 @@ typedef struct {
void rmd160_init( RMD160_CONTEXT *hd );
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*/

View File

@ -27,6 +27,7 @@
#include "memory.h"
#include "rmd.h"
#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)
@ -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
* the ALGO is invalid.
*/
const char *
static const char *
rmd160_get_info( int algo, size_t *contextsize,
byte **r_asnoid, int *r_asnlen, int *r_mdlen,
void (**r_init)( void *c ),
@ -582,3 +583,63 @@ rmd160_get_info( int algo, size_t *contextsize,
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);
continue;
}
if( errno == EPIPE ) /* parent has exited, so give up */
exit(0);
/* we can't do very much here because stderr is closed */
if( dbgfp )
fprintf(dbgfp, "gatherer can't write to pipe: %s\n",

View File

@ -38,7 +38,7 @@
#include <assert.h>
#include "util.h"
#include "memory.h"
#include "sha1.h"
#include "dynload.h"
typedef struct {
@ -331,7 +331,7 @@ sha1_read( SHA1_CONTEXT *hd )
* Returns: A pointer to string describing the algorithm or NULL if
* the ALGO is invalid.
*/
const char *
static const char *
sha1_get_info( int algo, size_t *contextsize,
byte **r_asnoid, int *r_asnlen, int *r_mdlen,
void (**r_init)( void *c ),
@ -358,3 +358,64 @@ sha1_get_info( int algo, size_t *contextsize,
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$)";
static struct {
@ -938,6 +941,9 @@ static struct {
* version = interface version of the function/pointer
* (currently this is 1 for all functions)
*/
#ifndef IS_MODULE
static
#endif
void *
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;
}
#ifndef IS_MODULE
void
tiger_constructor(void)
{
register_internal_cipher_extension( gnupgext_version,
gnupgext_enum_func );
}
#endif
#endif /* HAVE_U64_TYPEDEF */

View File

@ -24,6 +24,7 @@
#include "types.h" /* for byte and u32 typedefs */
#include "util.h"
#include "errors.h"
#include "dynload.h"
/* 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;
/* Check key length. */
if( keylen != 16 )
if( keylen != 16 ) /* enhance this code for 256 bit keys */
return G10ERR_WRONG_KEYLEN;
/* 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)
)
{
*keylen = 128;
*keylen = algo==10? 256 : 128;
*blocksize = 16;
*contextsize = sizeof (TWOFISH_context);
*r_setkey = FNCCAST_SETKEY (twofish_setkey);
*r_encrypt= FNCCAST_CRYPT (twofish_encrypt);
*r_decrypt= FNCCAST_CRYPT (twofish_decrypt);
if( algo == 10 )
return "TWOFISH";
if (algo == 102) /* This algorithm number is assigned for
* experiments, so we can use it */
return "TWOFISH";
return "TWOFISH128";
return NULL;
}
@ -863,6 +866,7 @@ static struct {
void (*func)(void);
} func_table[] = {
{ 20, 1, 0, (void(*)(void))twofish_get_info },
{ 21, 1, 10 },
{ 21, 1, 102 },
};

View File

@ -15,11 +15,15 @@ AM_CONFIG_HEADER(config.h)
VERSION=`cat $srcdir/VERSION`
PACKAGE=gnupg
ALL_LINGUAS="de es_ES fr it pl pt_BR ru"
static_modules="sha1 md5 rmd160"
AC_SUBST(VERSION)
AC_SUBST(PACKAGE)
AC_DEFINE_UNQUOTED(VERSION, "$VERSION")
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_ARG_ENABLE(dev-random,
[ --disable-dev-random disable the use of dev random],
@ -91,6 +95,8 @@ if test "$GCC" = yes; then
CFLAGS="$CFLAGS -Wall"
fi
try_gettext=yes
try_gdbm=yes
case "${target}" in
i386--mingw32)
# special stuff for Windoze NT
@ -99,9 +105,19 @@ case "${target}" in
CPP="i386--mingw32-gcc -E"
RANLIB="i386--mingw32-ranlib"
ac_cv_have_dev_random=no
AC_DEFINE(USE_RNDW32)
AC_DEFINE(USE_ONLY_8DOT3)
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*)
if test -z "$GCC" ; then
@ -126,6 +142,9 @@ case "${target}" in
i386--mingw32)
PRINTABLE_OS_NAME="MingW32"
;;
i386-emx-os2)
PRINTABLE_OS_NAME="OS/2"
;;
*-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.
if test "$try_gettext" = yes; then
AM_GNU_GETTEXT
fi
if test "$try_gdbm" = yes; then
AC_CHECK_LIB(gdbm,gdbm_firstkey)
fi
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])
if test "$ac_cv_have_dev_random" = yes; then
AC_DEFINE(HAVE_DEV_RANDOM)
AC_DEFINE(USE_RNDLINUX)
fi
else
AC_MSG_CHECKING(for random device)
@ -262,42 +284,93 @@ fi
dnl
dnl Figure how to link the random modules
dnl Figure out the default linkage mode for cipher modules
dnl
dnl (We always need a static rmd160)
static_modules="$static_modules rmd160"
if test "$ac_cv_have_dev_random" = yes; then
AC_DEFINE(USE_RNDLINUX)
STATIC_RANDOM_OBJS="rndlinux.o"
DYNAMIC_RANDOM_MODS=""
static_modules="$static_modules rndlinux"
else
case "${target}" in
i386--mingw32)
AC_DEFINE(USE_RNDW32)
STATIC_RANDOM_OBJS=""
DYNAMIC_RANDOM_MODS=""
static_modules="$static_modules rndw32"
;;
i386-emx-os2)
static_modules="$static_modules rndos2"
;;
m68k-atari-mint)
AC_DEFINE(USE_RNDATARI)
STATIC_RANDOM_OBJS=""
DYNAMIC_RANDOM_MODS=""
static_modules="$static_modules rndatari"
;;
*)
AC_DEFINE(USE_RNDUNIX)
STATIC_RANDOM_OBJS="rndunix.o"
DYNAMIC_RANDOM_MODS=""
static_modules="$static_modules rndunix"
;;
esac
fi
AC_SUBST(STATIC_RANDOM_OBJS)
AC_SUBST(DYNAMIC_RANDOM_MODS)
dnl
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 Figure how to link the cipher modules
dnl
dnl (form now these are only dynamic)
STATIC_CIPHER_OBJS=""
DYNAMIC_CIPHER_MODS="twofish tiger"
AC_SUBST(STATIC_CIPHER_OBJS)
AC_SUBST(DYNAMIC_CIPHER_MODS)
@ -351,6 +424,10 @@ fi
fi
AC_SUBST(ZLIBS)
if echo "$VERSION" | grep '[a-zA-Z]' >/dev/null ; then
AC_DEFINE(IS_DEVELOPMENT_VERSION)
fi
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.
BADARMOR
The ascii armor is corrupted. No arguments yet.
The ASCII armor is corrupted. No arguments yet.
RSA_OR_IDEA
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 byte ownertrust
1 byte dirflag
1 byte validity
1 byte validity of the key calucalted over all user ids
19 byte reserved
@ -208,7 +208,7 @@ Record type 4: (uid record)
1 u32 pointer to preference record
1 u32 siglist list of valid signatures
1 byte uidflags
1 byte reserved
1 byte validity of the key calculated over this user id
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
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
key.
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
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
with the secret
key. If someone has your public key, they can verify that it is from
you and that it hasn't changed by checking the encoded form of the
hash with the public key.
hash is taken of the data, and then the hash is in some form encoded with
the secret key. If someone has your public key, they can verify that it
is from you and that it hasn't changed by checking the encoded form of
the hash with the public key.
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
@ -63,12 +62,12 @@
or at a meeting of your local GNU/Linux User Group.
Hmm, what else. You may use the option "-o filename" to force output
to this filename (use "-" to force output to stdout).
"-r" just lets you specify the recipient (which public key you encrypt with)
on the command line instead of typing it interactively.
to this filename (use "-" to force output to stdout). "-r" just lets you
specify the recipient (which public key you encrypt with) on the command
line instead of typing it interactively.
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
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
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
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
ElGamal subkey which is created if the default key algorithm
is chosen. You may add an type 16 ElGamal key to your public
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
OpenPGP requires generation of V3 signatures for all kind of
data. Use the option "--force-v3-sigs" to generate V3 signatures
for data.
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
no direct way to do this. However it is not so complicated
do to it anyway: Create a new user id with exactly the same name,
you will notice that there are two identical user ids on the
secret ring now. Now select this user id and delete it; both
user ids from the secret ring will be removed.
no direct way to do this. However it is not very complicated
to do it anyway. Create a new user id with exactly the same name
and you will see that there are now two identical user ids on the
secret ring. Now select this user id and delete it. Both user
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
supported by GNUPG because it is patented, but if you have a modified
version of PGP you can try this:
@ -130,11 +129,11 @@
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
no-comment
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.
@ -142,42 +141,40 @@
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.
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
buffer is to play with your keyboard.
Good security has it's price.
What I do is to hit several times on the shift,control, alternate,
capslock keys, as these keys do not produce any output to the screen.
This way you get your keys really fast (it's the same thing pgp2 does).
talked to Ted Ts'o and he commented that the best way to fill the buffer
is to play with your keyboard. Good security has it's price. What I do
is to hit several times on the shift, control, alternate, and capslock
keys, because these keys do not produce output to the screen. 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
(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?
A: Don't do this at all!
You should never create keys or even use gnupg on a remote system because
you normally have
no physical control over your secret keyring (which is in most cases
vulnerable to advanced dictionary attacks) - I strongly encourage
everyone to only create keys on a local computer (a disconnected
laptop is probably the best choice) and if you need it on your
connected box (I know: We all do this) be sure to have a strong
password for your account, your secret key and trust your Root.
A: Don't do this at all! You should never create keys or even use gnupg
on a remote system because you normally have no physical control over
your secret keyring (which is in most cases vulnerable to advanced
dictionary attacks) - I strongly encourage everyone to only create keys
on a local computer (a disconnected laptop is probably the best choice)
and if you need it on your connected box (I know: We all do this) be
sure to have a strong password for your account and for your secret key
and trust your Root.
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,
so I use a special option --quick-random to generate insecure keys which are
only good for some tests.
I have the same problem. It takes a *very* long time to create the
keys, so I use a special option, --quick-random, to generate insecure
keys which are only good for some tests.
Q: How does the whole trust thing work?
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
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
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
(ownertrust) to a key. I have plans to use a cache for calculated
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
@ -193,13 +190,13 @@
is only used for keys for which
the secret key is also available.
You can get a list of the assigned trust values (how far you trust
the owner to correctly sign another one's key)
You can get a list of the assigned trust values (how much you trust
the owner to correctly sign another person's key)
gpgm --list-ownertrust
The first field is the fingerprint of the primary key, the second one
the assigned value:
The first field is the fingerprint of the primary key, the second field
is the assigned value:
- = No Ownertrust value yet assigned.
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.
u = No need to trust ourself because we have the secret key.
Please keep these values confidential, as they express some opinions of
you about others. PGP does store these information with the keyring, so
it is not a good idea to publish the keyring instead of exporting the
keyring - gnupg stores the trust in the trust-DB and therefor it is okay
to give the keyring away (but we have a --export command too).
Keep these values confidential because they express your opinions
about others. PGP stores this information with the keyring thus
it is not a good idea to publish a PGP keyring instead of exporting the
keyring. gnupg stores the trust in the trust-DB so it is okay
to give a gpg keyring away (but we have a --export command too).
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
of commands. The second is a list of options. Whenever you run GPG, you *must*
pick exactly one command (**with one exception, see below). You *may* pick one
or more options. The command should, just by convention, come at the end of the
argument list, after all the options. If the command takes a file (all the
basic ones do), the filename comes at the very end. So the basic way to
run gpg is:
A: If you do a "gpg --help", you will get two separate lists. The first is
a list of commands. The second is a list of options. Whenever you run GPG,
you *must* pick exactly one command (**with one exception, see below). You
*may* pick one or more options. The command should, just by convention,
come at the end of the argument list, after all the options. If the
command takes a file (all the basic ones do), the filename comes at the
very end. So the basic way to run gpg is:
gpg [--option something] [--option2] [--option3 something] --command file
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
must follow immediately after the option itself: otherwise gpg doesn't know
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
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
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
by the file you wish to encrypt. So use:
argument. The --encrypt (or -e) command comes after all the options followed
by the file you wish to encrypt. So use
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
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,
which doesn't take any arguments:
ASCII-armored text in there, so you need to add the --armor (-a) option,
which doesn't take any arguments.
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
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
@ -268,30 +265,30 @@
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.
"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.
Q: What is trust, validity and ownertrust?
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)
other keys. "validity" or calculated trust is a value which
says, how far the gnupg thinks a key is valid (that it really belongs
other keys. "validity", or calculated trust, is a value which
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).
For more see the chapter "The Web of Trust" in the
Manual [gpg: Oops: Internal error: manual not found - sorry]
Q: How do interpret some of the informational outputs:
A: While checking the validness of a key, GnuPG sometimes print
some informations which are prefixed with information about
the checked item:
Q: How do interpret some of the informational outputs?
A: While checking the validity of a key, GnuPG sometimes prints
some information which is prefixed with information about
the checked item.
"key 12345678.3456"
This is about the key with key ID 12345678 and the internal
number 3456, which is the record number of the so called
directory record in the trustdb.
"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
ring is printed.
"sig 12345678.3456/ACDE/9A8B7C6D"
@ -302,15 +299,14 @@
Q: How do I sign a patch file?
A: Use "gpg --clearsign --not-dash-escaped ...".
The problem with --clearsign is
that all lines starting with a dash are quoted with "- "; obviously
diff produces many of lines starting with a dash and these are
then quoted and that is not good for patch ;-). In order to use
a patch file without removing the cleartext signature, the special
option --not-dash-escaped may be used to suppress generation of
these escape sequences. You should not mail such a patch because
spaces and line endings are also subject to the signature and a mailer
may not preserve these. If you want to mail a file you can simply sign
it using your MUA.
The problem with --clearsign is that all lines starting with a dash are
quoted with "- "; obviously diff produces many of lines starting with a
dash and these are then quoted and that is not good for patch ;-). To
use a patch file without removing the cleartext signature, the special
option --not-dash-escaped may be used to suppress generation of these
escape sequences. You should not mail such a patch because spaces and
line endings are also subject to the signature and a mailer may not
preserve these. If you want to mail a file you can simply sign it
using your MUA.

View File

@ -67,7 +67,7 @@ B<-k> [I<username>] [I<keyring>]
Kludge to be somewhat compatible with PGP.
Without arguments, all public keyrings are 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.
B<-kv> Same as B<-k>
B<-kvv> List the signatures with every key.
@ -130,7 +130,7 @@ B<--edit-key> I<name>
Remove a subkey.
B<expire>
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
primary key is changed.
B<passwd>
@ -154,10 +154,10 @@ B<--edit-key> I<name>
key rings.
The listing shows you the key with its secondary
keys and all user ids. Selected keys or user ids
indicated by an asterisk. The trust value is
displayed with the primary key: The first one is the
assigned owner trust and the second the calculated
trust value; letters are used for the values:
are indicated by an asterisk. The trust value is
displayed with the primary key: the first is the
assigned owner trust and the second is the calculated
trust value. Letters are used for the values:
B<-> No ownertrust assigned / not yet calculated.
B<e> Trust calculation has failed.
B<q> Not enough information for calculation.
@ -201,11 +201,11 @@ B<--export-secret-keys> [I<names>]
B<--import>, B<--fast-import>
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>.
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].
B<--import-ownertrust> [I<filename>]
@ -215,9 +215,9 @@ B<--import-ownertrust> [I<filename>]
=head1 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
arguments if required. Lines with a hash as the first non-white-space
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
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
does not make sense.
@ -250,7 +250,7 @@ B<--trusted-key> I<keyid>
You may also use this option to skip the verification
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.
B<-r> I<name>, B<--recipient> I<name>
@ -268,7 +268,7 @@ B<-q>, B<--quiet>
B<-z> I<n>
Set compress level to I<n>. A value of 0 for I<n>
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>
Use canonical text mode. If B<-t> (but not
@ -276,17 +276,17 @@ B<-t>, B<--textmode>
and signing, this enables clearsigned messages.
This kludge is needed for PGP compatibility;
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>
Don't make any changes (not yet implemented).
B<--batch>
Batch mode; never ask, do not allow interactive
Use batch mode. Never ask, do not allow interactive
commands.
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.
B<--yes>
@ -297,7 +297,7 @@ B<--no>
B<--keyserver> I<name>
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
required for the command B<--send-keys> to
specify the keyserver to where the keys should
@ -374,11 +374,11 @@ B<--set-filename> I<string>
B<--completes-needed> I<n>
Number of completely trusted users to introduce a new
key signator (defaults to 1).
key signer (defaults to 1).
B<--marginals-needed> I<n>
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>
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.
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),
a I<1> (default) adds a salt to the passphrase and
I<3> iterates the whole process a couple of times.
@ -418,12 +418,12 @@ B<--s2k-mode> I<number>
B<--compress-algo> I<number>
Use compress algorithm I<number>. Default is I<2> which is
RFC1950 compression; you may use I<1> to use the old zlib
version which is used by PGP.
The default algorithm may give better
results because the window size is not limited to 8K.
If this is not used the OpenPGP behavior is used; i.e.
the compression algorithm is selected from the preferences.
RFC1950 compression. You may use I<1> to use the old zlib
version which is used by PGP. The default algorithm may
give better results because the window size is not limited
to 8K. If this is not used the OpenPGP behavior is used,
i.e. the compression algorithm is selected from the
preferences.
B<--digest-algo> I<name>
Use I<name> as message digest algorithm. Running the
@ -438,21 +438,20 @@ B<--throw-keyid>
process because all available secret keys are tried.
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
send such an armored file via email because all spaces
and line endings are hashed too. You can not use this
option for data which has 5 dashes somewhere at the
beginning of a line - patch files don't have this.
A special armor header line tells GnuPG about this
cleartext signature framework.
option for data which has 5 dashes at the beginning of a
line, patch files don't have this. A special armor header
line tells GnuPG about this cleartext signature option.
B<--escape-from-lines>
Because some mailers change lines starting with "From "
to ">From " it is good to handle such lines in a special
way when creating cleartext signatures; all other PGP
versions do it this way too. Because this would violate
rfc2440, this option is not enabled per default.
way when creating cleartext signatures. All other PGP
versions do it this way too. This option is not enabled
by default because it would violate rfc2440.
B<--passphrase-fd> I<n>
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.
B<--force-v3-sigs>
OpenPGP states that a implementation should generate
v4 signatures but PGP 5.x does only recognize such
signatures on key material. This options forces
v3 signatures for signatures on data.
OpenPGP states that an implementation should generate
v4 signatures but PGP 5.x recognizes v4 signatures only
on key material. This options forces v3 signatures for
signatures on data.
B<--lock-once>
Lock the file the first time a lock is requested
@ -510,7 +509,7 @@ B<-h>, B<--help>
=head1 RETURN VALUE
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
@ -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
whole system. Programs to do dictionary attacks on your secret keyring
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
is B<very> easy to spy out your passphrase!
=head1 BUGS
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
about insecure memory your OS kernel supports locking without being root;
setuid is dropped as soon as this memory is allocated.
On many systems this program should be installed as setuid(root). This
is necessary to lock memory pages. If you get no warning message about
insecure memory your OS kernel supports locking without being root.
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>
* 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, head_strings[afx->what] );
iobuf_writestr(a, "-----\n");
iobuf_writestr(a, "Version: GnuPG v" VERSION " ("
PRINTABLE_OS_NAME ")\n");
if( !opt.no_version )
iobuf_writestr(a, "Version: GnuPG v" VERSION " ("
PRINTABLE_OS_NAME ")\n");
if( opt.comment_string ) {
const char *s = opt.comment_string;
iobuf_writestr(a, "Comment: " );
for( ; *s; s++ ) {
if( *s == '\n' )
iobuf_writestr(a, "\\n" );
else if( *s == '\r' )
iobuf_writestr(a, "\\r" );
else if( *s == '\v' )
iobuf_writestr(a, "\\v" );
else
iobuf_put(a, *s );
if( *s ) {
iobuf_writestr(a, "Comment: " );
for( ; *s; s++ ) {
if( *s == '\n' )
iobuf_writestr(a, "\\n" );
else if( *s == '\r' )
iobuf_writestr(a, "\\r" );
else if( *s == '\v' )
iobuf_writestr(a, "\\v" );
else
iobuf_put(a, *s );
}
iobuf_put(a, '\n' );
}
iobuf_put(a, '\n' );
}
else
iobuf_writestr(a,

View File

@ -117,6 +117,7 @@ enum cmd_and_opt_values { aNull = 0,
oDebugAll,
oStatusFD,
oNoComment,
oNoVersion,
oCompletesNeeded,
oMarginalsNeeded,
oMaxCertDepth,
@ -307,6 +308,7 @@ static ARGPARSE_OPTS opts[] = {
{ oRunAsShmCP, "run-as-shm-coprocess", 4, "@" },
{ oSetFilename, "set-filename", 2, "@" },
{ oComment, "comment", 2, "@" },
{ oNoVersion, "no-version", 0, "@"},
{ oNotDashEscaped, "not-dash-escaped", 0, "@" },
{ oEscapeFrom, "escape-from-lines", 0, "@" },
{ oLockOnce, "lock-once", 0, "@" },
@ -716,6 +718,7 @@ main( int argc, char **argv )
opt.verbose = 0; opt.list_sigs=0; break;
case oQuickRandom: quick_random_gen(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 oMarginalsNeeded: opt.marginals_needed = 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 ) {
tty_printf("%s %s; %s\n", strusage(11), strusage(13), strusage(14) );
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 */
@ -859,12 +865,6 @@ main( int argc, char **argv )
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) )
g10_exit(2);

View File

@ -38,9 +38,9 @@
#define MAX_PK_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.
* 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.
* Note: We must use numerical values here in case that this program
* will be converted to those little blue HAL9000s with their strange
@ -95,6 +95,7 @@ struct getkey_ctx_s {
KBPOS kbpos;
int last_rc;
ulong count;
int not_allocated;
int nitems;
getkey_item_t items[1];
};
@ -322,11 +323,13 @@ get_pubkey( PKT_public_key *pk, u32 *keyid )
/* do a lookup */
{ struct getkey_ctx_s ctx;
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = 11;
ctx.items[0].keyid[0] = keyid[0];
ctx.items[0].keyid[1] = keyid[1];
rc = lookup_pk( &ctx, pk, NULL );
get_pubkey_end( &ctx );
}
if( !rc )
goto leave;
@ -371,11 +374,13 @@ get_seckey( PKT_secret_key *sk, u32 *keyid )
struct getkey_ctx_s ctx;
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = 11;
ctx.items[0].keyid[0] = keyid[0];
ctx.items[0].keyid[1] = keyid[1];
rc = lookup_sk( &ctx, sk, NULL );
get_seckey_end( &ctx );
if( !rc ) {
/* check the secret key (this may prompt for a passprase to
* unlock the secret key
@ -395,14 +400,18 @@ int
get_primary_seckey( PKT_secret_key *sk, u32 *keyid )
{
struct getkey_ctx_s ctx;
int rc;
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.primary = 1;
ctx.nitems = 1;
ctx.items[0].mode = 11;
ctx.items[0].keyid[0] = keyid[0];
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 );
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = 11;
ctx.items[0].keyid[0] = keyid[0];
ctx.items[0].keyid[1] = keyid[1];
rc = lookup_sk( &ctx, sk, NULL );
get_seckey_end( &ctx );
free_secret_key( sk );
return rc;
}
@ -653,9 +664,9 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
/* and call the lookup function */
ctx->primary = 1; /* we want to look for the primary key only */
if( sk )
rc = lookup_sk( ctx, sk, NULL );
rc = lookup_sk( ctx, sk, ret_kb );
else
rc = lookup_pk( ctx, pk, NULL );
rc = lookup_pk( ctx, pk, ret_kb );
if( retctx ) /* caller wants the context */
*retctx = ctx;
@ -733,7 +744,8 @@ get_pubkey_end( GETKEY_CTX ctx )
enum_keyblocks( 2, &ctx->kbpos, NULL ); /* close */
for(n=0; n < ctx->nitems; n++ )
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 ) {
struct getkey_ctx_s ctx;
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = fprint_len;
memcpy( ctx.items[0].fprint, fprint, fprint_len );
rc = lookup_pk( &ctx, pk, NULL );
get_pubkey_end( &ctx );
}
else
rc = G10ERR_GENERAL; /* Oops */
@ -772,10 +786,12 @@ get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint,
if( fprint_len == 20 || fprint_len == 16 ) {
struct getkey_ctx_s ctx;
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = fprint_len;
memcpy( ctx.items[0].fprint, fprint, fprint_len );
rc = lookup_pk( &ctx, pk, ret_keyblock );
get_pubkey_end( &ctx );
}
else
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;
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
ctx.primary = 1;
ctx.nitems = 1;
ctx.items[0].mode = 15;
rc = lookup_sk( &ctx, sk, NULL );
get_seckey_end( &ctx );
}
else {
add_to_strlist( &namelist, name );
@ -868,7 +886,8 @@ get_seckey_end( GETKEY_CTX ctx )
enum_keyblocks( 2, &ctx->kbpos, NULL ); /* close */
for(n=0; n < ctx->nitems; n++ )
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 );
else if( item->mode == 16 || item->mode == 20 )
k = find_by_fpr( ctx->keyblock, pk,
item->name, item->mode );
item->fprint, item->mode );
else
BUG();
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 );
else if( item->mode == 16 || item->mode == 20 )
k = find_by_fpr_sk( ctx->keyblock, sk,
item->name, item->mode );
item->fprint, item->mode );
else
BUG();
if( k ) {

View File

@ -83,15 +83,13 @@ keygen_add_std_prefs( PKT_signature *sig, void *opaque )
keygen_add_key_expire( sig, opaque );
buf[0] = CIPHER_ALGO_BLOWFISH;
buf[0] = CIPHER_ALGO_TWOFISH;
buf[1] = CIPHER_ALGO_CAST5;
build_sig_subpkt( sig, SIGSUBPKT_PREF_SYM, buf, 2 );
buf[0] = DIGEST_ALGO_RMD160;
buf[1] = DIGEST_ALGO_SHA1;
buf[2] = DIGEST_ALGO_TIGER;
buf[3] = DIGEST_ALGO_MD5;
build_sig_subpkt( sig, SIGSUBPKT_PREF_HASH, buf, 4 );
build_sig_subpkt( sig, SIGSUBPKT_PREF_HASH, buf, 2 );
buf[0] = 2;
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 );
if( !node ) {
log_error("Oops; key lost!\n");
dump_kbnode( keyblock );
return;
}

View File

@ -252,7 +252,11 @@ proc_plaintext( CTX c, PACKET *pkt )
free_md_filter_context( &c->mfx );
c->mfx.md = md_open( 0, 0);
/* 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;
for(n=c->list; n; n = n->next ) {
if( n->pkt->pkttype == PKT_ONEPASS_SIG ) {

View File

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

View File

@ -31,6 +31,7 @@
#include "trustdb.h"
#include "cipher.h"
#include "status.h"
#include "options.h"
#include "i18n.h"
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) )
log_error("can't check algorithm against preferences\n");
else if( dek->algo != CIPHER_ALGO_3DES
&& !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM, dek->algo ) )
log_info(_("NOTE: cipher algorithm %d not found in preferences\n"),
&& !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM, dek->algo ) ) {
/* 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 );
}
free_public_key( pk );
rc = 0;
}

View File

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

View File

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

View File

@ -77,7 +77,8 @@ struct cmp_sdir_struct {
static char *db_name;
static const char *lockname;
static DOTLOCK lockhandle;
static int is_locked;
static int db_fd = -1;
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 */
if( !n )
n = 1;
if( !lockname )
lockname = make_dotlock( db_name, -1 );
if( !lockname )
log_fatal("can't get a lock - giving up\n");
if( !is_locked ) {
if( make_dotlock( lockhandle, -1 ) )
log_fatal("can't acquire lock - giving up\n");
else
is_locked = 1;
}
for( unused = NULL, r = cache_list; r; r = r->next ) {
if( r->flags.used && r->flags.dirty ) {
int rc = write_cache_item( r );
@ -254,8 +257,8 @@ put_record_into_cache( ulong recno, const char *data )
}
}
if( !opt.lock_once ) {
release_dotlock( lockname );
lockname=NULL;
if( !release_dotlock( lockhandle ) )
is_locked = 0;
}
assert( unused );
r = unused;
@ -287,17 +290,20 @@ tdbio_sync()
CACHE_CTRL r;
int did_lock = 0;
if( db_fd == -1 )
open_db();
if( in_transaction )
log_bug("tdbio: syncing while in transaction\n");
if( !cache_is_dirty )
return 0;
if( !lockname ) {
lockname = make_dotlock( db_name, -1 );
if( !is_locked ) {
if( make_dotlock( lockhandle, -1 ) )
log_fatal("can't acquire lock - giving up\n");
else
is_locked = 1;
did_lock = 1;
if( !lockname )
log_fatal("can't get a lock - giving up\n");
}
for( r = cache_list; r; r = r->next ) {
if( r->flags.used && r->flags.dirty ) {
@ -308,8 +314,8 @@ tdbio_sync()
}
cache_is_dirty = 0;
if( did_lock && !opt.lock_once ) {
release_dotlock( lockname );
lockname=NULL;
if( !release_dotlock( lockhandle ) )
is_locked = 0;
}
return 0;
}
@ -344,17 +350,19 @@ tdbio_end_transaction()
if( !in_transaction )
log_bug("tdbio: no active transaction\n");
if( !lockname )
lockname = make_dotlock( db_name, -1 );
if( !lockname )
log_fatal("can't get a lock - giving up\n");
if( !is_locked ) {
if( make_dotlock( lockhandle, -1 ) )
log_fatal("can't acquire lock - giving up\n");
else
is_locked = 1;
}
block_all_signals();
in_transaction = 0;
rc = tdbio_sync();
unblock_all_signals();
if( !opt.lock_once ) {
release_dotlock( lockname );
lockname=NULL;
if( !release_dotlock( lockhandle ) )
is_locked = 0;
}
return rc;
}
@ -392,9 +400,9 @@ tdbio_cancel_transaction()
static void
cleanup(void)
{
if( lockname ) {
release_dotlock(lockname);
lockname = NULL;
if( is_locked ) {
if( !release_dotlock(lockhandle) )
is_locked = 0;
}
}
@ -428,7 +436,7 @@ tdbio_set_dbname( const char *new_dbname, int create )
if( access( fname, F_OK ) ) {
if( strlen(fname) >= 7
&& !strcmp(fname+strlen(fname)-7, "/.gnupg" ) ) {
#if __MINGW32__
#if HAVE_DOSISH_SYSTEM
if( mkdir( fname ) )
#else
if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) )
@ -450,7 +458,7 @@ tdbio_set_dbname( const char *new_dbname, int create )
fclose(fp);
m_free(db_name);
db_name = fname;
#ifdef __MINGW32__
#ifdef HAVE_DOSISH_SYSTEM
db_fd = open( db_name, O_RDWR | O_BINARY );
#else
db_fd = open( db_name, O_RDWR );
@ -501,7 +509,10 @@ open_db()
TRUSTREC rec;
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 );
#else
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.siglist,
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_VALID )
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.siglist = buftoulong(p); p += 4;
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);
break;
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.siglist); p += 4;
*p++ = rec->r.uid.uidflags;
p++;
*p++ = rec->r.uid.validity;
memcpy( p, rec->r.uid.namehash, 20 ); p += 20;
break;

View File

@ -59,9 +59,10 @@
#define KEYF_EXPIRED 4 /* this key is expired */
#define KEYF_REVOKED 8 /* this key has been revoked */
#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_REVOKED 8 /* this user id has been revoked */
#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_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_VALID 2 /* the signature is valid */
@ -98,7 +99,7 @@ struct trust_record {
ulong cacherec; /* the cache record */
byte ownertrust;
byte dirflags;
byte validity; /* calculated trustlevel */
byte validity; /* calculated trustlevel over all uids */
} dir;
struct { /* primary public key record */
ulong lid;
@ -114,6 +115,7 @@ struct trust_record {
ulong prefrec; /* recno of preference record */
ulong siglist; /* list of valid signatures (w/o self-sig)*/
byte uidflags;
byte validity; /* calculated trustlevel of this uid */
byte namehash[20]; /* ripemd hash of the username */
} uid;
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 qry_lid_table_flag( LOCAL_ID_TABLE tbl, ulong lid, unsigned *flag );
static void print_user_id( const char *text, u32 *keyid );
static void sort_tsl_list( TRUST_SEG_LIST *trust_seg_list );
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;
int marginal=0;
int fully=0;
LOCAL_ID_TABLE sigs_seen = NULL;
/*LOCAL_ID_TABLE sigs_seen = NULL;*/
if( depth >= max_depth ) /* max cert_depth reached */
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 */
if( !all )
sigs_seen = new_lid_table();
/*if( !all ) sigs_seen = new_lid_table();*/
for( rn = drec->r.dir.uidlist; rn; rn = uidrn ) {
TRUSTREC rec; /* used for uids and sigs */
ulong sigrn;
@ -888,7 +861,36 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
if( (rec.r.uid.uidflags & UIDF_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 ) {
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
* signed more than one user ID) */
if( sigs_seen && ins_lid_table_item( sigs_seen,
rec.r.sig.sig[i].lid, 0) )
continue; /* we already have this one */
* signed more than one user ID)
* if( sigs_seen && ins_lid_table_item( sigs_seen,
* rec.r.sig.sig[i].lid, 0) )
* continue; we already have this one
*/
read_record( rec.r.sig.sig[i].lid, &tmp, 0 );
if( tmp.rectype != RECTYPE_DIR ) {
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 assume that this one is fully trusted */
if( !all ) {
if( sigs_seen )
release_lid_table( sigs_seen );
/*if( sigs_seen ) release_lid_table( sigs_seen );*/
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
|| marginal >= opt.marginals_needed ) {
if( !all ) {
if( sigs_seen )
release_lid_table( sigs_seen );
/*if( sigs_seen ) release_lid_table( sigs_seen );*/
return (stack[depth].trust = TRUST_FULLY);
}
}
}
}
}
if( sigs_seen )
release_lid_table( sigs_seen );
/*if( sigs_seen ) release_lid_table( sigs_seen ); */
if( all && ( fully >= opt.completes_needed
|| marginal >= opt.marginals_needed ) ) {
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
* find a path to an ultimately trusted key. We do this by
@ -1337,6 +1475,7 @@ void
list_trust_path( const char *username )
{
int rc;
ulong lid;
TRUSTREC rec;
TRUST_INFO *tmppath;
TRUST_SEG_LIST trust_seg_list, tsl, tsl2;
@ -1357,8 +1496,10 @@ list_trust_path( const char *username )
assert( pk->local_id );
}
}
lid = pk->local_id;
free_public_key( pk );
#if 0
/* collect the paths */
tmppath = m_alloc_clear( (opt.max_cert_depth+1)* sizeof *tmppath );
trust_seg_list = NULL;
@ -1378,6 +1519,26 @@ list_trust_path( const char *username )
m_free( tsl );
}
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 */
}
if( rec.r.sig.sig[i].lid == pk_lid ) {
#if 0 /* must take uid into account */
if( found_sig ) {
log_info( "sig %08lX.%lu/%02X%02X/%08lX: %s\n",
(ulong)keyid[1], lid, uidhash[18],
uidhash[19], (ulong)sig->keyid[1],
_("Duplicated certificate - deleted") );
_("duplicated certificate - deleted") );
rec.r.sig.sig[i].lid = 0;
rec.dirty = 1;
continue;
}
#endif
found_sig = 1;
}
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;
/* 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>
* cipher.h (MD_BUFFER_SIZE): Removed.

View File

@ -33,9 +33,10 @@
#define CIPHER_ALGO_BLOWFISH 4 /* blowfish 128 bit key */
#define CIPHER_ALGO_SAFER_SK128 5
#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_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 PUBKEY_ALGO_RSA 1
@ -63,11 +64,9 @@ typedef struct {
byte key[24]; /* this is the largest used keylen (3des) */
} DEK;
struct cipher_handle_s;
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_CFB 2
@ -75,6 +74,8 @@ struct cipher_handle_s { char does_not_matter[1]; };
#define CIPHER_MODE_AUTO_CFB 4
#define CIPHER_MODE_DUMMY 5 /* used with algo DUMMY for no encryption */
struct md_digest_list_s;
typedef struct {
int secure;
FILE *debug;
@ -85,12 +86,6 @@ typedef struct {
} *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 g10_opt_verbose;

View File

@ -127,10 +127,12 @@ const char *strusage( int level );
/*-- dotlock.c --*/
const char *make_dotlock( const char *file_to_lock, long timeout );
int release_dotlock( const char *lockfile );
struct dotlock_handle;
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 --*/

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>
* 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>
* autogen.sh: Now checks for installed gettext

View File

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

6
scripts/config.sub vendored
View File

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

View File

@ -18,6 +18,10 @@ fix_it () {
EOF
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 <stdlib.h>
#include <string.h>
#ifdef __MINGW32__
#ifdef HAVE_DOSISH_SYSTEM
#include <io.h>
#include <fcntl.h>
#endif
@ -67,7 +67,7 @@ main(int argc, char **argv)
int n, size=4096;
int algo;
#ifdef __MINGW32__
#ifdef HAVE_DOSISH_SYSTEM
setmode( fileno(stdin), O_BINARY );
setmode( fileno(stdout), O_BINARY );
#endif

View File

@ -19,10 +19,10 @@
#include "ttyio.h"
#include "i18n.h"
#ifdef __MINGW32__
#ifdef HAVE_DOSISH_SYSTEM
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);
}
#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>
* http.c (http_wait_response): Moved the shutdown behind the dup

View File

@ -35,37 +35,56 @@
#include "util.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 void remove_lockfiles(void);
/****************
* Create a lockfile with the given name. A TIMEOUT of 0
* returns immediately, -1 waits forever (hopefully not), other
* values are timeouts in milliseconds.
* Returns: a char pointer used as handle for release lock
* or NULL in case of an error.
* Create a lockfile with the given name and return an object of
* type DOTLOCK which may be used later to actually do the lock.
* A cleanup routine gets installed to cleanup left over locks
* or other files used together with the lockmechanism.
* 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
* as file_to_lock with the name "file_to_lock.lock"
* A temporary file ".#lk.<hostname>.pid[.threadid] is used.
* This function does nothing for Windoze.
*/
const char *
make_dotlock( const char *file_to_lock, long timeout )
DOTLOCK
create_dotlock( const char *file_to_lock )
{
int fd=-1, pid;
static int initialized;
DOTLOCK h;
int fd = -1;
char pidstr[16];
const char *handle = NULL;
char *lockname = NULL;
char *tname = NULL;
int have_tfile = 0;
struct utsname uts;
const char *nodename;
const char *dirpart;
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() );
/* 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;
}
#ifdef _THREAD_SAFE
tname = m_alloc( dirpartlen + 6 + strlen(nodename) + 11+ 20 );
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() );
#ifdef _REENTRANT
/* fixme: aquire mutex on all_lockfiles */
#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 {
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 );
} while( fd == -1 && errno == EINTR );
if( fd == -1 ) {
log_error( "failed to create temporary file `%s': %s\n",
tname, strerror(errno));
goto leave;
h->tname, strerror(errno));
m_free(h->tname);
m_free(h);
return NULL;
}
have_tfile = 1;
if( write(fd, pidstr, 11 ) != 11 ) {
log_fatal( "error writing to `%s': %s\n", tname, strerror(errno) );
goto leave;
all_lockfiles = h->next;
#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) ) {
log_error( "error closing `%s': %s\n", tname, strerror(errno));
goto leave;
all_lockfiles = h->next;
#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 );
strcpy(stpcpy(lockname, file_to_lock), ".lock");
#ifdef _REENTRANT
/* 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:
if( !link(tname, lockname) ) {/* fixme: better use stat to check the link count */
handle = lockname;
lockname = NULL;
static int
maybe_deadlock( DOTLOCK h )
{
DOTLOCK r;
for( r=all_lockfiles; r; r = r->next ) {
if( r != h && r->locked )
return 1;
}
else if( errno == EEXIST ) {
if( (pid = read_lockfile(lockname)) == -1 ) {
if( errno == ENOENT ) {
log_info( "lockfile disappeared\n");
goto retry;
return 0;
}
/****************
* 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() ) {
log_info( "Oops: lock already hold by us\n");
handle = lockname;
lockname = NULL;
h->locked = 1;
return 0; /* okay */
}
else if( kill(pid, 0) && errno == ESRCH ) {
maybe_dead = " - probably dead";
#if 0 /* we should not do this without checking the permissions */
/* and the hostname */
log_info( "removing stale lockfile (created by %d)", pid );
remove( lockname );
goto retry;
#endif
}
if( timeout == -1 ) {
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 */
tv.tv_sec = 1 + backoff;
tv.tv_usec = 0;
select(0, NULL, NULL, NULL, &tv);
if( backoff < 10 )
backoff++ ;
goto retry;
}
/* fixme: implement timeouts */
else
return -1;
}
else
log_error( "lock not made: link() failed: %s\n", strerror(errno) );
leave:
if( fd != -1 )
close(fd);
if( have_tfile )
remove(tname);
m_free(tname);
m_free(lockname);
return handle;
/*not reached */
#endif /* !HAVE_DOSISH_SYSTEM */
}
/****************
* 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
* Returns: 0 := success
*/
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 ) {
log_error( "release_dotlock: lockfile error");
log_error( "release_dotlock: lockfile error\n");
return -1;
}
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;
}
if( remove( lockfile ) ) {
if( unlink( h->lockname ) ) {
log_error( "release_dotlock: error removing lockfile `%s'",
lockfile);
h->lockname);
return -1;
}
m_free( (char*)lockfile );
/* fixme: check that the link count is now 1 */
h->locked = 0;
return 0;
#endif /* !HAVE_DOSISH_SYSTEM */
}
@ -218,6 +286,9 @@ release_dotlock( const char *lockfile )
static int
read_lockfile( const char *name )
{
#ifdef HAVE_DOSISH_SYSTEM
return 0;
#else
int fd, pid;
char pidstr[16];
@ -241,5 +312,29 @@ read_lockfile( const char *name )
return -1;
}
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)
{
char *p;
if ( !(p=strrchr(filepath, '/')) )
#ifdef __MINGW32__
if ( !(p=strrchr(filepath, '\\')) )
if ( !(p=strrchr(filepath, ':')) )
#ifdef HAVE_DRIVE_LETTERS
if ( !(p=strrchr(filepath, '\\')) )
if ( !(p=strrchr(filepath, ':')) )
#endif
{
return m_strdup(filepath);
}
{
return m_strdup(filepath);
}
return m_strdup(p+1);
}
@ -65,21 +65,21 @@ make_dirname(const char *filepath)
char *dirname;
int dirname_length;
char *p;
if ( !(p=strrchr(filepath, '/')) )
#ifdef __MINGW32__
if ( !(p=strrchr(filepath, '\\')) )
if ( !(p=strrchr(filepath, ':')) )
#ifdef HAVE_DRIVE_LETTERS
if ( !(p=strrchr(filepath, '\\')) )
if ( !(p=strrchr(filepath, ':')) )
#endif
{
return m_strdup(".");
}
{
return m_strdup(".");
}
dirname_length = p-filepath;
dirname = m_alloc(dirname_length+1);
strncpy(dirname, filepath, dirname_length);
dirname[dirname_length] = 0;
return dirname;
}
@ -126,7 +126,7 @@ compare_filenames( const char *a, const char *b )
/* ? check whether this is an absolute filename and
* resolve symlinks?
*/
#ifdef __MINGW32__
#ifdef HAVE_DRIVE_LETTERS
return stricmp(a,b);
#else
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";
}
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);
}
fp = NULL;
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_INIT, NULL, NULL, &len );
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;
}

View File

@ -217,7 +217,7 @@ void
secmem_init( size_t n )
{
if( !n ) {
#ifndef __MINGW32__
#ifndef HAVE_DOSISH_SYSTEM
uid_t uid;
disable_secmem=1;
@ -245,8 +245,12 @@ secmem_malloc( size_t size )
MEMBLOCK *mb, *mb2;
int compressed=0;
if( !pool_okay )
log_bug("secmem not initialized\n");
if( !pool_okay ) {
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 ) {
show_warning = 0;
print_warn();

View File

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