mirror of
git://git.gnupg.org/gnupg.git
synced 2025-02-03 16:53:03 +01:00
This commit was manufactured by cvs2svn to create branch
'GNUPG-1-9-BRANCH-MO'.
This commit is contained in:
parent
4b3427c6ce
commit
6decea8316
625
ABOUT-NLS
625
ABOUT-NLS
@ -1,625 +0,0 @@
|
|||||||
Notes on the Free Translation Project
|
|
||||||
*************************************
|
|
||||||
|
|
||||||
Free software is going international! The Free Translation Project
|
|
||||||
is a way to get maintainers of free software, translators, and users all
|
|
||||||
together, so that will gradually become able to speak many languages.
|
|
||||||
A few packages already provide translations for their messages.
|
|
||||||
|
|
||||||
If you found this `ABOUT-NLS' file inside a distribution, you may
|
|
||||||
assume that the distributed package does use GNU `gettext' internally,
|
|
||||||
itself available at your nearest GNU archive site. But you do _not_
|
|
||||||
need to install GNU `gettext' prior to configuring, installing or using
|
|
||||||
this package with messages translated.
|
|
||||||
|
|
||||||
Installers will find here some useful hints. These notes also
|
|
||||||
explain how users should proceed for getting the programs to use the
|
|
||||||
available translations. They tell how people wanting to contribute and
|
|
||||||
work at translations should contact the appropriate team.
|
|
||||||
|
|
||||||
When reporting bugs in the `intl/' directory or bugs which may be
|
|
||||||
related to internationalization, you should tell about the version of
|
|
||||||
`gettext' which is used. The information can be found in the
|
|
||||||
`intl/VERSION' file, in internationalized packages.
|
|
||||||
|
|
||||||
Quick configuration advice
|
|
||||||
==========================
|
|
||||||
|
|
||||||
If you want to exploit the full power of internationalization, you
|
|
||||||
should configure it using
|
|
||||||
|
|
||||||
./configure --with-included-gettext
|
|
||||||
|
|
||||||
to force usage of internationalizing routines provided within this
|
|
||||||
package, despite the existence of internationalizing capabilities in the
|
|
||||||
operating system where this package is being installed. So far, only
|
|
||||||
the `gettext' implementation in the GNU C library version 2 provides as
|
|
||||||
many features (such as locale alias, message inheritance, automatic
|
|
||||||
charset conversion or plural form handling) as the implementation here.
|
|
||||||
It is also not possible to offer this additional functionality on top
|
|
||||||
of a `catgets' implementation. Future versions of GNU `gettext' will
|
|
||||||
very likely convey even more functionality. So it might be a good idea
|
|
||||||
to change to GNU `gettext' as soon as possible.
|
|
||||||
|
|
||||||
So you need _not_ provide this option if you are using GNU libc 2 or
|
|
||||||
you have installed a recent copy of the GNU gettext package with the
|
|
||||||
included `libintl'.
|
|
||||||
|
|
||||||
INSTALL Matters
|
|
||||||
===============
|
|
||||||
|
|
||||||
Some packages are "localizable" when properly installed; the
|
|
||||||
programs they contain can be made to speak your own native language.
|
|
||||||
Most such packages use GNU `gettext'. Other packages have their own
|
|
||||||
ways to internationalization, predating GNU `gettext'.
|
|
||||||
|
|
||||||
By default, this package will be installed to allow translation of
|
|
||||||
messages. It will automatically detect whether the system already
|
|
||||||
provides the GNU `gettext' functions. If not, the GNU `gettext' own
|
|
||||||
library will be used. This library is wholly contained within this
|
|
||||||
package, usually in the `intl/' subdirectory, so prior installation of
|
|
||||||
the GNU `gettext' package is _not_ required. Installers may use
|
|
||||||
special options at configuration time for changing the default
|
|
||||||
behaviour. The commands:
|
|
||||||
|
|
||||||
./configure --with-included-gettext
|
|
||||||
./configure --disable-nls
|
|
||||||
|
|
||||||
will respectively bypass any pre-existing `gettext' to use the
|
|
||||||
internationalizing routines provided within this package, or else,
|
|
||||||
_totally_ disable translation of messages.
|
|
||||||
|
|
||||||
When you already have GNU `gettext' installed on your system and run
|
|
||||||
configure without an option for your new package, `configure' will
|
|
||||||
probably detect the previously built and installed `libintl.a' file and
|
|
||||||
will decide to use this. This might be not what is desirable. You
|
|
||||||
should use the more recent version of the GNU `gettext' library. I.e.
|
|
||||||
if the file `intl/VERSION' shows that the library which comes with this
|
|
||||||
package is more recent, you should use
|
|
||||||
|
|
||||||
./configure --with-included-gettext
|
|
||||||
|
|
||||||
to prevent auto-detection.
|
|
||||||
|
|
||||||
The configuration process will not test for the `catgets' function
|
|
||||||
and therefore it will not be used. The reason is that even an
|
|
||||||
emulation of `gettext' on top of `catgets' could not provide all the
|
|
||||||
extensions of the GNU `gettext' library.
|
|
||||||
|
|
||||||
Internationalized packages have usually many `po/LL.po' files, where
|
|
||||||
LL gives an ISO 639 two-letter code identifying the language. Unless
|
|
||||||
translations have been forbidden at `configure' time by using the
|
|
||||||
`--disable-nls' switch, all available translations are installed
|
|
||||||
together with the package. However, the environment variable `LINGUAS'
|
|
||||||
may be set, prior to configuration, to limit the installed set.
|
|
||||||
`LINGUAS' should then contain a space separated list of two-letter
|
|
||||||
codes, stating which languages are allowed.
|
|
||||||
|
|
||||||
Using This Package
|
|
||||||
==================
|
|
||||||
|
|
||||||
As a user, if your language has been installed for this package, you
|
|
||||||
only have to set the `LANG' environment variable to the appropriate
|
|
||||||
`LL_CC' combination. Here `LL' is an ISO 639 two-letter language code,
|
|
||||||
and `CC' is an ISO 3166 two-letter country code. For example, let's
|
|
||||||
suppose that you speak German and live in Germany. At the shell
|
|
||||||
prompt, merely execute `setenv LANG de_DE' (in `csh'),
|
|
||||||
`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash').
|
|
||||||
This can be done from your `.login' or `.profile' file, once and for
|
|
||||||
all.
|
|
||||||
|
|
||||||
You might think that the country code specification is redundant.
|
|
||||||
But in fact, some languages have dialects in different countries. For
|
|
||||||
example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The
|
|
||||||
country code serves to distinguish the dialects.
|
|
||||||
|
|
||||||
The locale naming convention of `LL_CC', with `LL' denoting the
|
|
||||||
language and `CC' denoting the country, is the one use on systems based
|
|
||||||
on GNU libc. On other systems, some variations of this scheme are
|
|
||||||
used, such as `LL' or `LL_CC.ENCODING'. You can get the list of
|
|
||||||
locales supported by your system for your country by running the command
|
|
||||||
`locale -a | grep '^LL''.
|
|
||||||
|
|
||||||
Not all programs have translations for all languages. By default, an
|
|
||||||
English message is shown in place of a nonexistent translation. If you
|
|
||||||
understand other languages, you can set up a priority list of languages.
|
|
||||||
This is done through a different environment variable, called
|
|
||||||
`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG'
|
|
||||||
for the purpose of message handling, but you still need to have `LANG'
|
|
||||||
set to the primary language; this is required by other parts of the
|
|
||||||
system libraries. For example, some Swedish users who would rather
|
|
||||||
read translations in German than English for when Swedish is not
|
|
||||||
available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'.
|
|
||||||
|
|
||||||
In the `LANGUAGE' environment variable, but not in the `LANG'
|
|
||||||
environment variable, `LL_CC' combinations can be abbreviated as `LL'
|
|
||||||
to denote the language's main dialect. For example, `de' is equivalent
|
|
||||||
to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT'
|
|
||||||
(Portuguese as spoken in Portugal) in this context.
|
|
||||||
|
|
||||||
Translating Teams
|
|
||||||
=================
|
|
||||||
|
|
||||||
For the Free Translation Project to be a success, we need interested
|
|
||||||
people who like their own language and write it well, and who are also
|
|
||||||
able to synergize with other translators speaking the same language.
|
|
||||||
Each translation team has its own mailing list. The up-to-date list of
|
|
||||||
teams can be found at the Free Translation Project's homepage,
|
|
||||||
`http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams"
|
|
||||||
area.
|
|
||||||
|
|
||||||
If you'd like to volunteer to _work_ at translating messages, you
|
|
||||||
should become a member of the translating team for your own language.
|
|
||||||
The subscribing address is _not_ the same as the list itself, it has
|
|
||||||
`-request' appended. For example, speakers of Swedish can send a
|
|
||||||
message to `sv-request@li.org', having this message body:
|
|
||||||
|
|
||||||
subscribe
|
|
||||||
|
|
||||||
Keep in mind that team members are expected to participate
|
|
||||||
_actively_ in translations, or at solving translational difficulties,
|
|
||||||
rather than merely lurking around. If your team does not exist yet and
|
|
||||||
you want to start one, or if you are unsure about what to do or how to
|
|
||||||
get started, please write to `translation@iro.umontreal.ca' to reach the
|
|
||||||
coordinator for all translator teams.
|
|
||||||
|
|
||||||
The English team is special. It works at improving and uniformizing
|
|
||||||
the terminology in use. Proven linguistic skill are praised more than
|
|
||||||
programming skill, here.
|
|
||||||
|
|
||||||
Available Packages
|
|
||||||
==================
|
|
||||||
|
|
||||||
Languages are not equally supported in all packages. The following
|
|
||||||
matrix shows the current state of internationalization, as of May 2003.
|
|
||||||
The matrix shows, in regard of each package, for which languages PO
|
|
||||||
files have been submitted to translation coordination, with a
|
|
||||||
translation percentage of at least 50%.
|
|
||||||
|
|
||||||
Ready PO files am az be bg ca cs da de el en en_GB eo es
|
|
||||||
+-------------------------------------------+
|
|
||||||
a2ps | [] [] [] [] |
|
|
||||||
aegis | () |
|
|
||||||
anubis | |
|
|
||||||
ap-utils | |
|
|
||||||
bash | [] [] [] |
|
|
||||||
batchelor | |
|
|
||||||
bfd | [] [] |
|
|
||||||
binutils | [] [] |
|
|
||||||
bison | [] [] [] |
|
|
||||||
bluez-pin | [] [] |
|
|
||||||
clisp | |
|
|
||||||
clisp | [] [] [] |
|
|
||||||
coreutils | [] [] [] [] |
|
|
||||||
cpio | [] [] [] |
|
|
||||||
darkstat | () [] |
|
|
||||||
diffutils | [] [] [] [] [] [] [] |
|
|
||||||
e2fsprogs | [] [] |
|
|
||||||
enscript | [] [] [] [] |
|
|
||||||
error | [] [] [] [] [] |
|
|
||||||
fetchmail | [] () [] [] [] [] |
|
|
||||||
fileutils | [] [] [] |
|
|
||||||
findutils | [] [] [] [] [] [] |
|
|
||||||
flex | [] [] [] [] |
|
|
||||||
gas | [] |
|
|
||||||
gawk | [] [] [] [] |
|
|
||||||
gcal | [] |
|
|
||||||
gcc | [] [] |
|
|
||||||
gettext | [] [] [] [] [] |
|
|
||||||
gettext-runtime | [] [] [] [] [] |
|
|
||||||
gettext-tools | [] [] |
|
|
||||||
gimp-print | [] [] [] [] [] |
|
|
||||||
gliv | |
|
|
||||||
glunarclock | [] [] [] |
|
|
||||||
gnucash | () [] |
|
|
||||||
gnucash-glossary | [] () [] |
|
|
||||||
gnupg | [] () [] [] [] [] |
|
|
||||||
gpe-calendar | [] |
|
|
||||||
gpe-conf | [] |
|
|
||||||
gpe-contacts | [] |
|
|
||||||
gpe-edit | |
|
|
||||||
gpe-login | [] |
|
|
||||||
gpe-ownerinfo | [] |
|
|
||||||
gpe-sketchbook | [] |
|
|
||||||
gpe-timesheet | |
|
|
||||||
gpe-today | [] |
|
|
||||||
gpe-todo | [] |
|
|
||||||
gphoto2 | [] [] [] [] |
|
|
||||||
gprof | [] [] |
|
|
||||||
gpsdrive | () () () |
|
|
||||||
grep | [] [] [] [] [] |
|
|
||||||
gretl | [] |
|
|
||||||
hello | [] [] [] [] [] [] |
|
|
||||||
id-utils | [] [] |
|
|
||||||
indent | [] [] [] [] |
|
|
||||||
jpilot | [] [] [] [] |
|
|
||||||
jwhois | [] |
|
|
||||||
kbd | [] [] [] [] [] |
|
|
||||||
ld | [] [] |
|
|
||||||
libc | [] [] [] [] [] [] |
|
|
||||||
libgpewidget | [] |
|
|
||||||
libiconv | [] [] [] [] [] |
|
|
||||||
lifelines | [] () |
|
|
||||||
lilypond | [] |
|
|
||||||
lingoteach | |
|
|
||||||
lingoteach_lessons | () () |
|
|
||||||
lynx | [] [] [] [] |
|
|
||||||
m4 | [] [] [] [] |
|
|
||||||
mailutils | [] [] |
|
|
||||||
make | [] [] [] |
|
|
||||||
man-db | [] () [] [] () |
|
|
||||||
mysecretdiary | [] [] [] |
|
|
||||||
nano | [] () [] [] [] |
|
|
||||||
nano_1_0 | [] () [] [] [] |
|
|
||||||
opcodes | [] [] |
|
|
||||||
parted | [] [] [] [] [] |
|
|
||||||
ptx | [] [] [] [] [] |
|
|
||||||
python | |
|
|
||||||
radius | |
|
|
||||||
recode | [] [] [] [] [] [] |
|
|
||||||
screem | |
|
|
||||||
sed | [] [] [] [] [] |
|
|
||||||
sh-utils | [] [] [] |
|
|
||||||
sharutils | [] [] [] [] [] [] |
|
|
||||||
sketch | [] () [] |
|
|
||||||
soundtracker | [] [] [] |
|
|
||||||
sp | [] |
|
|
||||||
tar | [] [] [] [] |
|
|
||||||
texinfo | [] [] [] [] |
|
|
||||||
textutils | [] [] [] [] |
|
|
||||||
tin | () () |
|
|
||||||
util-linux | [] [] [] [] [] |
|
|
||||||
vorbis-tools | [] [] [] |
|
|
||||||
wastesedge | () |
|
|
||||||
wdiff | [] [] [] [] |
|
|
||||||
wget | [] [] [] [] [] [] [] |
|
|
||||||
xchat | [] [] [] |
|
|
||||||
xpad | |
|
|
||||||
+-------------------------------------------+
|
|
||||||
am az be bg ca cs da de el en en_GB eo es
|
|
||||||
0 1 4 2 31 17 54 60 14 1 4 12 56
|
|
||||||
|
|
||||||
et fa fi fr ga gl he hr hu id it ja ko
|
|
||||||
+----------------------------------------+
|
|
||||||
a2ps | [] [] [] () () |
|
|
||||||
aegis | |
|
|
||||||
anubis | [] |
|
|
||||||
ap-utils | [] |
|
|
||||||
bash | [] [] |
|
|
||||||
batchelor | [] |
|
|
||||||
bfd | [] [] |
|
|
||||||
binutils | [] [] |
|
|
||||||
bison | [] [] [] [] |
|
|
||||||
bluez-pin | [] [] [] [] |
|
|
||||||
clisp | |
|
|
||||||
clisp | [] |
|
|
||||||
coreutils | [] [] [] [] |
|
|
||||||
cpio | [] [] [] [] |
|
|
||||||
darkstat | () [] [] [] |
|
|
||||||
diffutils | [] [] [] [] [] [] [] |
|
|
||||||
e2fsprogs | |
|
|
||||||
enscript | [] [] |
|
|
||||||
error | [] [] [] [] |
|
|
||||||
fetchmail | [] |
|
|
||||||
fileutils | [] [] [] [] [] |
|
|
||||||
findutils | [] [] [] [] [] [] [] [] [] [] [] |
|
|
||||||
flex | [] [] |
|
|
||||||
gas | [] |
|
|
||||||
gawk | [] [] |
|
|
||||||
gcal | [] |
|
|
||||||
gcc | [] |
|
|
||||||
gettext | [] [] [] |
|
|
||||||
gettext-runtime | [] [] [] [] |
|
|
||||||
gettext-tools | [] |
|
|
||||||
gimp-print | [] [] |
|
|
||||||
gliv | () |
|
|
||||||
glunarclock | [] [] [] [] |
|
|
||||||
gnucash | [] |
|
|
||||||
gnucash-glossary | [] |
|
|
||||||
gnupg | [] [] [] [] [] [] [] |
|
|
||||||
gpe-calendar | [] |
|
|
||||||
gpe-conf | |
|
|
||||||
gpe-contacts | [] |
|
|
||||||
gpe-edit | [] [] |
|
|
||||||
gpe-login | [] |
|
|
||||||
gpe-ownerinfo | [] [] [] |
|
|
||||||
gpe-sketchbook | [] |
|
|
||||||
gpe-timesheet | [] [] [] |
|
|
||||||
gpe-today | [] [] |
|
|
||||||
gpe-todo | [] [] |
|
|
||||||
gphoto2 | [] [] [] |
|
|
||||||
gprof | [] [] |
|
|
||||||
gpsdrive | () [] () () |
|
|
||||||
grep | [] [] [] [] [] [] [] [] [] [] [] |
|
|
||||||
gretl | [] |
|
|
||||||
hello | [] [] [] [] [] [] [] [] [] [] [] [] [] |
|
|
||||||
id-utils | [] [] [] |
|
|
||||||
indent | [] [] [] [] [] [] [] [] |
|
|
||||||
jpilot | [] () |
|
|
||||||
jwhois | [] [] [] [] |
|
|
||||||
kbd | [] |
|
|
||||||
ld | [] |
|
|
||||||
libc | [] [] [] [] [] [] |
|
|
||||||
libgpewidget | [] [] [] |
|
|
||||||
libiconv | [] [] [] [] [] [] [] [] |
|
|
||||||
lifelines | () |
|
|
||||||
lilypond | [] |
|
|
||||||
lingoteach | [] [] |
|
|
||||||
lingoteach_lessons | |
|
|
||||||
lynx | [] [] [] [] |
|
|
||||||
m4 | [] [] [] [] |
|
|
||||||
mailutils | |
|
|
||||||
make | [] [] [] [] [] [] |
|
|
||||||
man-db | [] () () |
|
|
||||||
mysecretdiary | [] [] |
|
|
||||||
nano | [] [] [] [] |
|
|
||||||
nano_1_0 | [] [] [] [] |
|
|
||||||
opcodes | [] [] |
|
|
||||||
parted | [] [] [] |
|
|
||||||
ptx | [] [] [] [] [] [] [] |
|
|
||||||
python | |
|
|
||||||
radius | |
|
|
||||||
recode | [] [] [] [] [] [] |
|
|
||||||
screem | |
|
|
||||||
sed | [] [] [] [] [] [] [] [] |
|
|
||||||
sh-utils | [] [] [] [] [] [] |
|
|
||||||
sharutils | [] [] [] [] [] |
|
|
||||||
sketch | [] |
|
|
||||||
soundtracker | [] [] [] |
|
|
||||||
sp | [] () |
|
|
||||||
tar | [] [] [] [] [] [] [] [] [] |
|
|
||||||
texinfo | [] [] [] [] |
|
|
||||||
textutils | [] [] [] [] [] |
|
|
||||||
tin | [] () |
|
|
||||||
util-linux | [] [] [] [] () [] |
|
|
||||||
vorbis-tools | [] |
|
|
||||||
wastesedge | () |
|
|
||||||
wdiff | [] [] [] [] [] |
|
|
||||||
wget | [] [] [] [] [] [] [] [] |
|
|
||||||
xchat | [] [] [] |
|
|
||||||
xpad | |
|
|
||||||
+----------------------------------------+
|
|
||||||
et fa fi fr ga gl he hr hu id it ja ko
|
|
||||||
20 1 15 73 14 24 8 10 30 31 19 31 9
|
|
||||||
|
|
||||||
lg lt lv ms nb nl nn no pl pt pt_BR ro
|
|
||||||
+----------------------------------------+
|
|
||||||
a2ps | [] [] () () () [] [] |
|
|
||||||
aegis | () |
|
|
||||||
anubis | [] [] |
|
|
||||||
ap-utils | () |
|
|
||||||
bash | [] |
|
|
||||||
batchelor | |
|
|
||||||
bfd | |
|
|
||||||
binutils | |
|
|
||||||
bison | [] [] [] [] |
|
|
||||||
bluez-pin | [] |
|
|
||||||
clisp | |
|
|
||||||
clisp | [] |
|
|
||||||
coreutils | [] |
|
|
||||||
cpio | [] [] [] |
|
|
||||||
darkstat | [] [] [] [] |
|
|
||||||
diffutils | [] [] [] |
|
|
||||||
e2fsprogs | |
|
|
||||||
enscript | [] [] |
|
|
||||||
error | [] [] |
|
|
||||||
fetchmail | () () |
|
|
||||||
fileutils | [] |
|
|
||||||
findutils | [] [] [] [] |
|
|
||||||
flex | [] |
|
|
||||||
gas | |
|
|
||||||
gawk | [] |
|
|
||||||
gcal | |
|
|
||||||
gcc | |
|
|
||||||
gettext | [] |
|
|
||||||
gettext-runtime | [] |
|
|
||||||
gettext-tools | |
|
|
||||||
gimp-print | [] |
|
|
||||||
gliv | [] |
|
|
||||||
glunarclock | [] |
|
|
||||||
gnucash | |
|
|
||||||
gnucash-glossary | [] [] |
|
|
||||||
gnupg | |
|
|
||||||
gpe-calendar | [] [] |
|
|
||||||
gpe-conf | [] [] |
|
|
||||||
gpe-contacts | [] |
|
|
||||||
gpe-edit | [] [] |
|
|
||||||
gpe-login | [] [] |
|
|
||||||
gpe-ownerinfo | [] [] |
|
|
||||||
gpe-sketchbook | [] [] |
|
|
||||||
gpe-timesheet | [] [] |
|
|
||||||
gpe-today | [] [] |
|
|
||||||
gpe-todo | [] [] |
|
|
||||||
gphoto2 | |
|
|
||||||
gprof | [] |
|
|
||||||
gpsdrive | () () () |
|
|
||||||
grep | [] [] [] [] |
|
|
||||||
gretl | |
|
|
||||||
hello | [] [] [] [] [] [] [] [] [] |
|
|
||||||
id-utils | [] [] [] |
|
|
||||||
indent | [] [] [] |
|
|
||||||
jpilot | () () |
|
|
||||||
jwhois | [] [] [] |
|
|
||||||
kbd | |
|
|
||||||
ld | |
|
|
||||||
libc | [] [] [] [] |
|
|
||||||
libgpewidget | [] [] |
|
|
||||||
libiconv | [] [] |
|
|
||||||
lifelines | |
|
|
||||||
lilypond | [] |
|
|
||||||
lingoteach | |
|
|
||||||
lingoteach_lessons | |
|
|
||||||
lynx | [] [] |
|
|
||||||
m4 | [] [] [] [] |
|
|
||||||
mailutils | |
|
|
||||||
make | [] [] |
|
|
||||||
man-db | [] |
|
|
||||||
mysecretdiary | [] |
|
|
||||||
nano | [] [] [] [] |
|
|
||||||
nano_1_0 | [] [] [] [] |
|
|
||||||
opcodes | [] [] [] |
|
|
||||||
parted | [] [] [] |
|
|
||||||
ptx | [] [] [] [] [] [] [] |
|
|
||||||
python | |
|
|
||||||
radius | |
|
|
||||||
recode | [] [] [] |
|
|
||||||
screem | |
|
|
||||||
sed | [] [] |
|
|
||||||
sh-utils | [] |
|
|
||||||
sharutils | [] |
|
|
||||||
sketch | [] |
|
|
||||||
soundtracker | |
|
|
||||||
sp | |
|
|
||||||
tar | [] [] [] [] [] [] |
|
|
||||||
texinfo | [] |
|
|
||||||
textutils | [] |
|
|
||||||
tin | |
|
|
||||||
util-linux | [] [] |
|
|
||||||
vorbis-tools | [] [] |
|
|
||||||
wastesedge | |
|
|
||||||
wdiff | [] [] [] [] |
|
|
||||||
wget | [] [] [] |
|
|
||||||
xchat | [] [] |
|
|
||||||
xpad | [] |
|
|
||||||
+----------------------------------------+
|
|
||||||
lg lt lv ms nb nl nn no pl pt pt_BR ro
|
|
||||||
0 0 2 11 7 26 3 4 18 15 34 34
|
|
||||||
|
|
||||||
ru sk sl sr sv ta tr uk vi wa zh_CN zh_TW
|
|
||||||
+-------------------------------------------+
|
|
||||||
a2ps | [] [] [] [] [] | 16
|
|
||||||
aegis | () | 0
|
|
||||||
anubis | [] [] | 5
|
|
||||||
ap-utils | () | 1
|
|
||||||
bash | [] | 7
|
|
||||||
batchelor | | 1
|
|
||||||
bfd | [] [] [] | 7
|
|
||||||
binutils | [] [] [] | 7
|
|
||||||
bison | [] [] | 13
|
|
||||||
bluez-pin | | 7
|
|
||||||
clisp | | 0
|
|
||||||
clisp | | 5
|
|
||||||
coreutils | [] [] [] [] [] | 14
|
|
||||||
cpio | [] [] [] | 13
|
|
||||||
darkstat | [] () () | 9
|
|
||||||
diffutils | [] [] [] [] | 21
|
|
||||||
e2fsprogs | [] | 3
|
|
||||||
enscript | [] [] [] | 11
|
|
||||||
error | [] [] [] | 14
|
|
||||||
fetchmail | [] | 7
|
|
||||||
fileutils | [] [] [] [] [] [] | 15
|
|
||||||
findutils | [] [] [] [] [] [] | 27
|
|
||||||
flex | [] [] [] | 10
|
|
||||||
gas | [] | 3
|
|
||||||
gawk | [] [] | 9
|
|
||||||
gcal | [] [] | 4
|
|
||||||
gcc | [] | 4
|
|
||||||
gettext | [] [] [] [] [] [] | 15
|
|
||||||
gettext-runtime | [] [] [] [] [] [] | 16
|
|
||||||
gettext-tools | [] [] | 5
|
|
||||||
gimp-print | [] [] | 10
|
|
||||||
gliv | | 1
|
|
||||||
glunarclock | [] [] [] | 11
|
|
||||||
gnucash | [] [] | 4
|
|
||||||
gnucash-glossary | [] [] [] | 8
|
|
||||||
gnupg | [] [] [] [] | 16
|
|
||||||
gpe-calendar | [] | 5
|
|
||||||
gpe-conf | | 3
|
|
||||||
gpe-contacts | [] | 4
|
|
||||||
gpe-edit | [] | 5
|
|
||||||
gpe-login | [] | 5
|
|
||||||
gpe-ownerinfo | [] | 7
|
|
||||||
gpe-sketchbook | [] | 5
|
|
||||||
gpe-timesheet | [] | 6
|
|
||||||
gpe-today | [] | 6
|
|
||||||
gpe-todo | [] | 6
|
|
||||||
gphoto2 | [] [] | 9
|
|
||||||
gprof | [] [] | 7
|
|
||||||
gpsdrive | [] [] | 3
|
|
||||||
grep | [] [] [] [] | 24
|
|
||||||
gretl | | 2
|
|
||||||
hello | [] [] [] [] [] | 33
|
|
||||||
id-utils | [] [] [] | 11
|
|
||||||
indent | [] [] [] [] | 19
|
|
||||||
jpilot | [] [] [] [] [] | 10
|
|
||||||
jwhois | () () [] [] | 10
|
|
||||||
kbd | [] [] | 8
|
|
||||||
ld | [] [] | 5
|
|
||||||
libc | [] [] [] [] | 20
|
|
||||||
libgpewidget | | 6
|
|
||||||
libiconv | [] [] [] [] [] [] | 21
|
|
||||||
lifelines | [] | 2
|
|
||||||
lilypond | [] | 4
|
|
||||||
lingoteach | | 2
|
|
||||||
lingoteach_lessons | () | 0
|
|
||||||
lynx | [] [] [] [] | 14
|
|
||||||
m4 | [] [] [] | 15
|
|
||||||
mailutils | | 2
|
|
||||||
make | [] [] [] [] | 15
|
|
||||||
man-db | [] | 6
|
|
||||||
mysecretdiary | [] [] | 8
|
|
||||||
nano | [] [] [] | 15
|
|
||||||
nano_1_0 | [] [] [] | 15
|
|
||||||
opcodes | [] [] | 9
|
|
||||||
parted | [] [] | 13
|
|
||||||
ptx | [] [] [] | 22
|
|
||||||
python | | 0
|
|
||||||
radius | | 0
|
|
||||||
recode | [] [] [] [] | 19
|
|
||||||
screem | [] | 1
|
|
||||||
sed | [] [] [] [] [] | 20
|
|
||||||
sh-utils | [] [] [] | 13
|
|
||||||
sharutils | [] [] [] [] | 16
|
|
||||||
sketch | [] | 5
|
|
||||||
soundtracker | [] | 7
|
|
||||||
sp | [] | 3
|
|
||||||
tar | [] [] [] [] [] | 24
|
|
||||||
texinfo | [] [] [] [] | 13
|
|
||||||
textutils | [] [] [] [] [] | 15
|
|
||||||
tin | | 1
|
|
||||||
util-linux | [] [] | 14
|
|
||||||
vorbis-tools | [] | 7
|
|
||||||
wastesedge | | 0
|
|
||||||
wdiff | [] [] [] [] | 17
|
|
||||||
wget | [] [] [] [] [] [] [] | 25
|
|
||||||
xchat | [] [] [] | 11
|
|
||||||
xpad | | 1
|
|
||||||
+-------------------------------------------+
|
|
||||||
50 teams ru sk sl sr sv ta tr uk vi wa zh_CN zh_TW
|
|
||||||
97 domains 32 19 16 0 56 0 48 10 1 1 12 23 913
|
|
||||||
|
|
||||||
Some counters in the preceding matrix are higher than the number of
|
|
||||||
visible blocks let us expect. This is because a few extra PO files are
|
|
||||||
used for implementing regional variants of languages, or language
|
|
||||||
dialects.
|
|
||||||
|
|
||||||
For a PO file in the matrix above to be effective, the package to
|
|
||||||
which it applies should also have been internationalized and
|
|
||||||
distributed as such by its maintainer. There might be an observable
|
|
||||||
lag between the mere existence a PO file and its wide availability in a
|
|
||||||
distribution.
|
|
||||||
|
|
||||||
If May 2003 seems to be old, you may fetch a more recent copy of
|
|
||||||
this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date
|
|
||||||
matrix with full percentage details can be found at
|
|
||||||
`http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'.
|
|
||||||
|
|
||||||
Using `gettext' in new packages
|
|
||||||
===============================
|
|
||||||
|
|
||||||
If you are writing a freely available program and want to
|
|
||||||
internationalize it you are welcome to use GNU `gettext' in your
|
|
||||||
package. Of course you have to respect the GNU Library General Public
|
|
||||||
License which covers the use of the GNU `gettext' library. This means
|
|
||||||
in particular that even non-free programs can use `libintl' as a shared
|
|
||||||
library, whereas only free software can use `libintl' as a static
|
|
||||||
library or use modified versions of `libintl'.
|
|
||||||
|
|
||||||
Once the sources are changed appropriately and the setup can handle
|
|
||||||
the use of `gettext' the only thing missing are the translations. The
|
|
||||||
Free Translation Project is also available for packages which are not
|
|
||||||
developed inside the GNU project. Therefore the information given above
|
|
||||||
applies also for every other Free Software Project. Contact
|
|
||||||
`translation@iro.umontreal.ca' to make the `.pot' files available to
|
|
||||||
the translation teams.
|
|
||||||
|
|
340
COPYING
340
COPYING
@ -1,340 +0,0 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
Version 2, June 1991
|
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
|
||||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
|
||||||
License is intended to guarantee your freedom to share and change free
|
|
||||||
software--to make sure the software is free for all its users. This
|
|
||||||
General Public License applies to most of the Free Software
|
|
||||||
Foundation's software and to any other program whose authors commit to
|
|
||||||
using it. (Some other Free Software Foundation software is covered by
|
|
||||||
the GNU Library General Public License instead.) You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
this service if you wish), that you receive source code or can get it
|
|
||||||
if you want it, that you can change the software or use pieces of it
|
|
||||||
in new free programs; and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
|
||||||
anyone to deny you these rights or to ask you to surrender the rights.
|
|
||||||
These restrictions translate to certain responsibilities for you if you
|
|
||||||
distribute copies of the software, or if you modify it.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must give the recipients all the rights that
|
|
||||||
you have. You must make sure that they, too, receive or can get the
|
|
||||||
source code. And you must show them these terms so they know their
|
|
||||||
rights.
|
|
||||||
|
|
||||||
We protect your rights with two steps: (1) copyright the software, and
|
|
||||||
(2) offer you this license which gives you legal permission to copy,
|
|
||||||
distribute and/or modify the software.
|
|
||||||
|
|
||||||
Also, for each author's protection and ours, we want to make certain
|
|
||||||
that everyone understands that there is no warranty for this free
|
|
||||||
software. If the software is modified by someone else and passed on, we
|
|
||||||
want its recipients to know that what they have is not the original, so
|
|
||||||
that any problems introduced by others will not reflect on the original
|
|
||||||
authors' reputations.
|
|
||||||
|
|
||||||
Finally, any free program is threatened constantly by software
|
|
||||||
patents. We wish to avoid the danger that redistributors of a free
|
|
||||||
program will individually obtain patent licenses, in effect making the
|
|
||||||
program proprietary. To prevent this, we have made it clear that any
|
|
||||||
patent must be licensed for everyone's free use or not licensed at all.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License applies to any program or other work which contains
|
|
||||||
a notice placed by the copyright holder saying it may be distributed
|
|
||||||
under the terms of this General Public License. The "Program", below,
|
|
||||||
refers to any such program or work, and a "work based on the Program"
|
|
||||||
means either the Program or any derivative work under copyright law:
|
|
||||||
that is to say, a work containing the Program or a portion of it,
|
|
||||||
either verbatim or with modifications and/or translated into another
|
|
||||||
language. (Hereinafter, translation is included without limitation in
|
|
||||||
the term "modification".) Each licensee is addressed as "you".
|
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running the Program is not restricted, and the output from the Program
|
|
||||||
is covered only if its contents constitute a work based on the
|
|
||||||
Program (independent of having been made by running the Program).
|
|
||||||
Whether that is true depends on what the Program does.
|
|
||||||
|
|
||||||
1. You may copy and distribute verbatim copies of the Program's
|
|
||||||
source code as you receive it, in any medium, provided that you
|
|
||||||
conspicuously and appropriately publish on each copy an appropriate
|
|
||||||
copyright notice and disclaimer of warranty; keep intact all the
|
|
||||||
notices that refer to this License and to the absence of any warranty;
|
|
||||||
and give any other recipients of the Program a copy of this License
|
|
||||||
along with the Program.
|
|
||||||
|
|
||||||
You may charge a fee for the physical act of transferring a copy, and
|
|
||||||
you may at your option offer warranty protection in exchange for a fee.
|
|
||||||
|
|
||||||
2. You may modify your copy or copies of the Program or any portion
|
|
||||||
of it, thus forming a work based on the Program, and copy and
|
|
||||||
distribute such modifications or work under the terms of Section 1
|
|
||||||
above, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) You must cause the modified files to carry prominent notices
|
|
||||||
stating that you changed the files and the date of any change.
|
|
||||||
|
|
||||||
b) You must cause any work that you distribute or publish, that in
|
|
||||||
whole or in part contains or is derived from the Program or any
|
|
||||||
part thereof, to be licensed as a whole at no charge to all third
|
|
||||||
parties under the terms of this License.
|
|
||||||
|
|
||||||
c) If the modified program normally reads commands interactively
|
|
||||||
when run, you must cause it, when started running for such
|
|
||||||
interactive use in the most ordinary way, to print or display an
|
|
||||||
announcement including an appropriate copyright notice and a
|
|
||||||
notice that there is no warranty (or else, saying that you provide
|
|
||||||
a warranty) and that users may redistribute the program under
|
|
||||||
these conditions, and telling the user how to view a copy of this
|
|
||||||
License. (Exception: if the Program itself is interactive but
|
|
||||||
does not normally print such an announcement, your work based on
|
|
||||||
the Program is not required to print an announcement.)
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
|
||||||
identifiable sections of that work are not derived from the Program,
|
|
||||||
and can be reasonably considered independent and separate works in
|
|
||||||
themselves, then this License, and its terms, do not apply to those
|
|
||||||
sections when you distribute them as separate works. But when you
|
|
||||||
distribute the same sections as part of a whole which is a work based
|
|
||||||
on the Program, the distribution of the whole must be on the terms of
|
|
||||||
this License, whose permissions for other licensees extend to the
|
|
||||||
entire whole, and thus to each and every part regardless of who wrote it.
|
|
||||||
|
|
||||||
Thus, it is not the intent of this section to claim rights or contest
|
|
||||||
your rights to work written entirely by you; rather, the intent is to
|
|
||||||
exercise the right to control the distribution of derivative or
|
|
||||||
collective works based on the Program.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Program
|
|
||||||
with the Program (or with a work based on the Program) on a volume of
|
|
||||||
a storage or distribution medium does not bring the other work under
|
|
||||||
the scope of this License.
|
|
||||||
|
|
||||||
3. You may copy and distribute the Program (or a work based on it,
|
|
||||||
under Section 2) in object code or executable form under the terms of
|
|
||||||
Sections 1 and 2 above provided that you also do one of the following:
|
|
||||||
|
|
||||||
a) Accompany it with the complete corresponding machine-readable
|
|
||||||
source code, which must be distributed under the terms of Sections
|
|
||||||
1 and 2 above on a medium customarily used for software interchange; or,
|
|
||||||
|
|
||||||
b) Accompany it with a written offer, valid for at least three
|
|
||||||
years, to give any third party, for a charge no more than your
|
|
||||||
cost of physically performing source distribution, a complete
|
|
||||||
machine-readable copy of the corresponding source code, to be
|
|
||||||
distributed under the terms of Sections 1 and 2 above on a medium
|
|
||||||
customarily used for software interchange; or,
|
|
||||||
|
|
||||||
c) Accompany it with the information you received as to the offer
|
|
||||||
to distribute corresponding source code. (This alternative is
|
|
||||||
allowed only for noncommercial distribution and only if you
|
|
||||||
received the program in object code or executable form with such
|
|
||||||
an offer, in accord with Subsection b above.)
|
|
||||||
|
|
||||||
The source code for a work means the preferred form of the work for
|
|
||||||
making modifications to it. For an executable work, complete source
|
|
||||||
code means all the source code for all modules it contains, plus any
|
|
||||||
associated interface definition files, plus the scripts used to
|
|
||||||
control compilation and installation of the executable. However, as a
|
|
||||||
special exception, the source code distributed need not include
|
|
||||||
anything that is normally distributed (in either source or binary
|
|
||||||
form) with the major components (compiler, kernel, and so on) of the
|
|
||||||
operating system on which the executable runs, unless that component
|
|
||||||
itself accompanies the executable.
|
|
||||||
|
|
||||||
If distribution of executable or object code is made by offering
|
|
||||||
access to copy from a designated place, then offering equivalent
|
|
||||||
access to copy the source code from the same place counts as
|
|
||||||
distribution of the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
4. You may not copy, modify, sublicense, or distribute the Program
|
|
||||||
except as expressly provided under this License. Any attempt
|
|
||||||
otherwise to copy, modify, sublicense or distribute the Program is
|
|
||||||
void, and will automatically terminate your rights under this License.
|
|
||||||
However, parties who have received copies, or rights, from you under
|
|
||||||
this License will not have their licenses terminated so long as such
|
|
||||||
parties remain in full compliance.
|
|
||||||
|
|
||||||
5. You are not required to accept this License, since you have not
|
|
||||||
signed it. However, nothing else grants you permission to modify or
|
|
||||||
distribute the Program or its derivative works. These actions are
|
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
|
||||||
modifying or distributing the Program (or any work based on the
|
|
||||||
Program), you indicate your acceptance of this License to do so, and
|
|
||||||
all its terms and conditions for copying, distributing or modifying
|
|
||||||
the Program or works based on it.
|
|
||||||
|
|
||||||
6. Each time you redistribute the Program (or any work based on the
|
|
||||||
Program), the recipient automatically receives a license from the
|
|
||||||
original licensor to copy, distribute or modify the Program subject to
|
|
||||||
these terms and conditions. You may not impose any further
|
|
||||||
restrictions on the recipients' exercise of the rights granted herein.
|
|
||||||
You are not responsible for enforcing compliance by third parties to
|
|
||||||
this License.
|
|
||||||
|
|
||||||
7. If, as a consequence of a court judgment or allegation of patent
|
|
||||||
infringement or for any other reason (not limited to patent issues),
|
|
||||||
conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot
|
|
||||||
distribute so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you
|
|
||||||
may not distribute the Program at all. For example, if a patent
|
|
||||||
license would not permit royalty-free redistribution of the Program by
|
|
||||||
all those who receive copies directly or indirectly through you, then
|
|
||||||
the only way you could satisfy both it and this License would be to
|
|
||||||
refrain entirely from distribution of the Program.
|
|
||||||
|
|
||||||
If any portion of this section is held invalid or unenforceable under
|
|
||||||
any particular circumstance, the balance of the section is intended to
|
|
||||||
apply and the section as a whole is intended to apply in other
|
|
||||||
circumstances.
|
|
||||||
|
|
||||||
It is not the purpose of this section to induce you to infringe any
|
|
||||||
patents or other property right claims or to contest validity of any
|
|
||||||
such claims; this section has the sole purpose of protecting the
|
|
||||||
integrity of the free software distribution system, which is
|
|
||||||
implemented by public license practices. Many people have made
|
|
||||||
generous contributions to the wide range of software distributed
|
|
||||||
through that system in reliance on consistent application of that
|
|
||||||
system; it is up to the author/donor to decide if he or she is willing
|
|
||||||
to distribute software through any other system and a licensee cannot
|
|
||||||
impose that choice.
|
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
|
||||||
be a consequence of the rest of this License.
|
|
||||||
|
|
||||||
8. If the distribution and/or use of the Program is restricted in
|
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
|
||||||
original copyright holder who places the Program under this License
|
|
||||||
may add an explicit geographical distribution limitation excluding
|
|
||||||
those countries, so that distribution is permitted only in or among
|
|
||||||
countries not thus excluded. In such case, this License incorporates
|
|
||||||
the limitation as if written in the body of this License.
|
|
||||||
|
|
||||||
9. The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the Program
|
|
||||||
specifies a version number of this License which applies to it and "any
|
|
||||||
later version", you have the option of following the terms and conditions
|
|
||||||
either of that version or of any later version published by the Free
|
|
||||||
Software Foundation. If the Program does not specify a version number of
|
|
||||||
this License, you may choose any version ever published by the Free Software
|
|
||||||
Foundation.
|
|
||||||
|
|
||||||
10. If you wish to incorporate parts of the Program into other free
|
|
||||||
programs whose distribution conditions are different, write to the author
|
|
||||||
to ask for permission. For software which is copyrighted by the Free
|
|
||||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
|
||||||
make exceptions for this. Our decision will be guided by the two goals
|
|
||||||
of preserving the free status of all derivatives of our free software and
|
|
||||||
of promoting the sharing and reuse of software generally.
|
|
||||||
|
|
||||||
NO WARRANTY
|
|
||||||
|
|
||||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
|
||||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
|
||||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
|
||||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
|
||||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
|
||||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
|
||||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
|
||||||
REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
|
||||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
|
||||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
|
||||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
|
||||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
|
||||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
|
||||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGES.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
convey the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This program 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.
|
|
||||||
|
|
||||||
This program 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
|
|
||||||
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program is interactive, make it output a short notice like this
|
|
||||||
when it starts in an interactive mode:
|
|
||||||
|
|
||||||
Gnomovision version 69, Copyright (C) year name of author
|
|
||||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type `show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, the commands you use may
|
|
||||||
be called something other than `show w' and `show c'; they could even be
|
|
||||||
mouse-clicks or menu items--whatever suits your program.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
|
||||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
|
||||||
necessary. Here is a sample; alter the names:
|
|
||||||
|
|
||||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
|
||||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
|
||||||
|
|
||||||
<signature of Ty Coon>, 1 April 1989
|
|
||||||
Ty Coon, President of Vice
|
|
||||||
|
|
||||||
This General Public License does not permit incorporating your program into
|
|
||||||
proprietary programs. If your program is a subroutine library, you may
|
|
||||||
consider it more useful to permit linking proprietary applications with the
|
|
||||||
library. If this is what you want to do, use the GNU Library General
|
|
||||||
Public License instead of this License.
|
|
452
ChangeLog
452
ChangeLog
@ -1,452 +0,0 @@
|
|||||||
2004-06-08 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 1.9.9.
|
|
||||||
|
|
||||||
2004-06-06 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Require libksba 0.9.7.
|
|
||||||
|
|
||||||
2004-04-29 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 1.9.8.
|
|
||||||
|
|
||||||
2004-04-20 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Remove the fopencookie test. We don't need the
|
|
||||||
dummy function because we conditionally use fopencookie,
|
|
||||||
fpencookie or a replacement at place.
|
|
||||||
|
|
||||||
2004-04-02 Thomas Schwinge <schwinge@nic-nac-project.de>
|
|
||||||
|
|
||||||
* autogen.sh: Added ACLOCAL_FLAGS.
|
|
||||||
|
|
||||||
2004-04-06 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 1.9.7.
|
|
||||||
|
|
||||||
* configure.ac: Require libgcrypt 1.1.94.
|
|
||||||
Introduce PACKAGE_GT and set it to gnupg2.
|
|
||||||
|
|
||||||
2004-03-23 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Define SAFE_VERSION_DASH and SAFE_VERSION_DOT.
|
|
||||||
|
|
||||||
2004-03-09 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac (NEED_GPG_ERROR_VERSION): Set to 0.7.
|
|
||||||
|
|
||||||
2004-03-06 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 1.9.6.
|
|
||||||
|
|
||||||
* configure.ac: Check the Libgcrypt API.
|
|
||||||
|
|
||||||
2004-02-25 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: New option --disable-threads to inhibit
|
|
||||||
unintentional builds without Pth.
|
|
||||||
|
|
||||||
2004-02-21 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 1.9.5.
|
|
||||||
|
|
||||||
2004-02-20 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Fixed URLs in the notice messages.
|
|
||||||
|
|
||||||
2004-02-18 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* acinclude.m4: Removed macros to detect gpg-error, libgcrypt,
|
|
||||||
libassuan and ksba as they are now distributed in m4/.
|
|
||||||
|
|
||||||
2004-02-13 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Require libksba 0.9.4 and libgcrypt 1.1.92.
|
|
||||||
|
|
||||||
2004-02-12 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* autogen.sh: Removed cruft from debugging.
|
|
||||||
|
|
||||||
* am/cmacros.am: New.
|
|
||||||
|
|
||||||
2004-02-11 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Removed the need for g10defs.h. Reworked the
|
|
||||||
--with-foo-pgm stuff.
|
|
||||||
|
|
||||||
* autogen.sh (check_version): Removed bashism and simplified.
|
|
||||||
* acinclude.m4 (AM_PATH_OPENSC): Kludge to avoid error output for
|
|
||||||
a bad opensc-config.
|
|
||||||
|
|
||||||
2004-01-30 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 1.9.4.
|
|
||||||
|
|
||||||
* configure.ac: Require libksba 0.9.3 due to another bug fix there.
|
|
||||||
|
|
||||||
2004-01-29 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* README: Updated.
|
|
||||||
|
|
||||||
* configure.ac: Require libksba 0.9.2 due to bug fixes.
|
|
||||||
|
|
||||||
2004-01-24 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Now requires libassuan 0.6.3.
|
|
||||||
|
|
||||||
2003-12-23 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 1.9.3.
|
|
||||||
|
|
||||||
* README-alpha: Removed.
|
|
||||||
* configure.ac, Makefile.am: Add the tests and tools directories.
|
|
||||||
|
|
||||||
2003-12-19 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Now require libgcrypt 1.1.91 to help testing the
|
|
||||||
latest libgcrypt changes. Requires libksab 0.9.1.
|
|
||||||
|
|
||||||
2003-12-17 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Requires now libassuan 0.6.2.
|
|
||||||
(CFLAGS): Add --Wformat-noliteral in gcc mode.
|
|
||||||
|
|
||||||
2003-12-16 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Check for funopen and fopencookie as part of the
|
|
||||||
jnlib checks.
|
|
||||||
|
|
||||||
2003-12-09 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Add a min_automake_version.
|
|
||||||
* README.CVS: New.
|
|
||||||
* autogen.sh: Revamped except for the --build-w32 hack.
|
|
||||||
* Makefile.am: Add README.CVS
|
|
||||||
|
|
||||||
2003-11-17 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Release 1.9.2.
|
|
||||||
|
|
||||||
* configure.ac: Requires now libassuan 0.6.1.
|
|
||||||
|
|
||||||
2003-10-31 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac (NEED_KSBA_VERSION): Set to 0.9.0 due the changed
|
|
||||||
time interface.
|
|
||||||
|
|
||||||
2003-10-21 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac (PRINTABLE_OS_NAME): Remove special case for The
|
|
||||||
Hurd; Robert Millan reported that the uname test is now
|
|
||||||
sufficient.
|
|
||||||
|
|
||||||
2003-10-01 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac (AH_BOTTOM): Define GNUPG_MAJOR_VERSION.
|
|
||||||
|
|
||||||
2003-09-23 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Merged most of David Shaw's changes in 1.3 since 2003-06-03.
|
|
||||||
|
|
||||||
* configure.ac: Drop all TIGER/192 support.
|
|
||||||
(uint64_t): Check for UINT64_C to go along with uint64_t.
|
|
||||||
(getaddrinfo): Check for it.
|
|
||||||
(sigset_t): Check for sigset_t and struct sigaction. This is for
|
|
||||||
Forte c89 on Solaris which seems to define only the function call
|
|
||||||
half of the two pairs by default.
|
|
||||||
(W32LIBS): Include wsock32 in W32LIBS. This is different from
|
|
||||||
NETLIBS so we don't need to force other platforms to pull in the
|
|
||||||
netlibs when they aren't actually needed.
|
|
||||||
|
|
||||||
2003-09-06 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 1.9.1.
|
|
||||||
|
|
||||||
* configure.ac: Require newer versions of some libraries.
|
|
||||||
|
|
||||||
2003-09-02 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac (HAVE_LIBUSB): Added a simple test for libusb.
|
|
||||||
|
|
||||||
2003-08-19 Marcus Brinkmann <marcus@g10code.de>
|
|
||||||
|
|
||||||
* configure.ac (AM_PATH_GPG_ERROR): Add missing comma in
|
|
||||||
invocation.
|
|
||||||
|
|
||||||
2003-08-06 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Check for libgpg-error. Print infos about missing
|
|
||||||
libraries more nicely.
|
|
||||||
* acinclude.m4 (AM_PATH_GPG_ERROR): Added.
|
|
||||||
|
|
||||||
2003-08-05 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 1.9.0.
|
|
||||||
|
|
||||||
* configure.ac (GNUPG_DEFAULT_HONMEDIR): Changed back to ~/.gnupg.
|
|
||||||
|
|
||||||
2003-07-31 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* Makefile.am (DISTCLEANFILES): Add g10defs.h
|
|
||||||
|
|
||||||
2003-06-18 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac (GNUPG_DEFAULT_HOMEDIR): Changed temporary to
|
|
||||||
.gnupg2 to avoid accidential use with production keys.
|
|
||||||
|
|
||||||
2003-06-11 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Merged all stuff from current 1.3 version in.
|
|
||||||
* acinclude.m4: Merged required macros from current 1.2 version in.
|
|
||||||
|
|
||||||
2003-06-04 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac, Makefile.am: Enable building of gpg.
|
|
||||||
|
|
||||||
2003-04-29 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Build a limited version of scdaemon if libopensc
|
|
||||||
is not available.
|
|
||||||
|
|
||||||
* configure.ac (ALL_LINUGAS): Removed.
|
|
||||||
|
|
||||||
* Makefile.am (ACLOCAL_AMFLAGS): New.
|
|
||||||
* configure.ac (AM_GNU_GETTEXT_VERSION): New. Set to 0.11.5.
|
|
||||||
|
|
||||||
2003-04-29 gettextize <bug-gnu-gettext@gnu.org>
|
|
||||||
|
|
||||||
* Makefile.am (SUBDIRS): Add m4.
|
|
||||||
(ACLOCAL_AMFLAGS): New variable.
|
|
||||||
(EXTRA_DIST): Add scripts/config.rpath.
|
|
||||||
* configure.ac (AC_CONFIG_FILES): Add m4/Makefile.
|
|
||||||
|
|
||||||
2003-04-29 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* assuan/ : Removed. We now use libassuan.
|
|
||||||
* Makefile.am (SUBDIRS): Removed assuan
|
|
||||||
|
|
||||||
* configure.ac: Check for libassuan.
|
|
||||||
|
|
||||||
2003-01-09 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac (GNUPG_PROTECT_TOOL): New option --with-protect-tool.
|
|
||||||
(NEED_KSBA_VERSION): Does now require 0.4.6.
|
|
||||||
|
|
||||||
* README: Noted where to find gpg-protect-tool.
|
|
||||||
|
|
||||||
2002-10-31 Neal H. Walfield <neal@g10code.de>
|
|
||||||
|
|
||||||
* configure.ac: Check for flockfile and funlockfile. Check for
|
|
||||||
isascii and putc_unlocked replacing them if not found.
|
|
||||||
|
|
||||||
* configure.ac (PTH_LIBS): If pth is found, add the output of
|
|
||||||
`$PTH_CONFIG --ldflags`, not just `$PTH_CONFIG --libs`.
|
|
||||||
|
|
||||||
2002-10-19 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Bumped version number to 1.9.0-cvs.
|
|
||||||
|
|
||||||
NewPG (Aegypten project) to GnuPG merge.
|
|
||||||
|
|
||||||
2002-09-20 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 0.9.2.
|
|
||||||
|
|
||||||
2002-09-05 Neal H. Walfield <neal@g10code.de>
|
|
||||||
|
|
||||||
* configure.ac: Check for makeinfo.
|
|
||||||
|
|
||||||
2002-09-03 Neal H. Walfield <neal@g10code.de>
|
|
||||||
|
|
||||||
* autogen.sh (have_version): New function. Generalize and
|
|
||||||
simplify logic for finding and determining the versions of GNU
|
|
||||||
programs. Use it.
|
|
||||||
|
|
||||||
2002-08-23 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 0.9.1.
|
|
||||||
|
|
||||||
* acinclude.m4 (AM_PATH_LIBGCRYPT): Updated from Libgcrypt.
|
|
||||||
(AM_PATH_OPENSC): Strip non-digits from the micro version.
|
|
||||||
|
|
||||||
2002-08-21 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 0.9.0.
|
|
||||||
|
|
||||||
* configure.ac: Changed the default homedir to .gnupg.
|
|
||||||
* README-alpha: Removed.
|
|
||||||
|
|
||||||
2002-08-19 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* acinclude.m4: Removed -lpcsclite from KSBA_LIBS; copy+paste bug.
|
|
||||||
|
|
||||||
2002-08-13 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* acinclude.m4 (AM_PATH_OPENSC, AM_PATH_KSBA): New.
|
|
||||||
* configure.ac: Use them.
|
|
||||||
|
|
||||||
2002-08-10 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 0.3.10.
|
|
||||||
|
|
||||||
* configure.ac (NEED_LIBKSBA_VERSION): Require 0.4.4. Add support
|
|
||||||
for gettext.
|
|
||||||
|
|
||||||
2002-07-22 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Check for ftello and provide a replacement.
|
|
||||||
|
|
||||||
2002-07-01 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 0.3.9.
|
|
||||||
|
|
||||||
* README: Short note on how to export in pkcs-12 format.
|
|
||||||
|
|
||||||
2002-06-29 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Define --with options to set the default location
|
|
||||||
of the agent, scdaemon, pinentry and dirmngr.
|
|
||||||
|
|
||||||
2002-06-27 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* README: Short blurb on how to import a PKCS-12 file.
|
|
||||||
|
|
||||||
* configure.ac (AH_BOTTOM): New to define some constants.
|
|
||||||
|
|
||||||
2002-06-25 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 0.3.8.
|
|
||||||
|
|
||||||
* configure.ac (NEED_LIBGCRYPT_VERSION): Set to 1.1.8.
|
|
||||||
|
|
||||||
2002-06-12 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac (NEED_LIBKSBA_VERSION): We need 0.4.3 now.
|
|
||||||
|
|
||||||
2002-06-04 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 0.3.7.
|
|
||||||
|
|
||||||
2002-05-21 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: We now require libgcrypt 1.1.7 and libksba 0.4.2.
|
|
||||||
|
|
||||||
2002-05-14 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* doc/: New
|
|
||||||
* configure.ac, Makefile.am: Added doc/
|
|
||||||
|
|
||||||
2002-05-03 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 0.3.6.
|
|
||||||
|
|
||||||
2002-04-25 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Check for setlocale.
|
|
||||||
|
|
||||||
2002-04-24 Marcus Brinkmann <marcus@g10code.de>
|
|
||||||
|
|
||||||
* configure.ac: Check for locale.h.
|
|
||||||
|
|
||||||
2002-04-15 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 0.3.5.
|
|
||||||
|
|
||||||
* NEWS: Started to describe release notes.
|
|
||||||
|
|
||||||
* configure.ac (NEED_LIBKSBA_VERSION, NEED_LIBGCRYPT_VERSION): Defined
|
|
||||||
|
|
||||||
2002-04-01 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 0.3.4.
|
|
||||||
|
|
||||||
2002-03-18 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 0.3.3.
|
|
||||||
|
|
||||||
2002-03-08 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* README: Add some explanation on how to specify a user ID.
|
|
||||||
|
|
||||||
2002-03-06 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 0.3.2.
|
|
||||||
|
|
||||||
2002-03-04 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 0.3.1.
|
|
||||||
|
|
||||||
* README: Explained some options and files.
|
|
||||||
|
|
||||||
2002-02-14 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Fixed status messages related to presence of Pth.
|
|
||||||
|
|
||||||
2002-02-13 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* acinclude.m4 (GNUPG_SYS_SO_PEERCRED): New.
|
|
||||||
* configure.ac: use it.
|
|
||||||
|
|
||||||
2002-02-12 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Check for PTH. Provide replacement fucntions for
|
|
||||||
apsrintf and fopencookie.
|
|
||||||
|
|
||||||
* acinclude.m4 (GNUPG_PTH_VERSION_CHECK): New.
|
|
||||||
|
|
||||||
2002-02-07 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 0.3.0.
|
|
||||||
|
|
||||||
* configure.ac: Require libgcrypt 1.1.6.
|
|
||||||
|
|
||||||
2002-02-01 Marcus Brinkmann <marcus@g10code.de>
|
|
||||||
|
|
||||||
* configure.ac (KSBA_CONFIG): Remove superfluous x in front of
|
|
||||||
variable.
|
|
||||||
|
|
||||||
2002-01-26 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac: Add options to disable the build of some programs
|
|
||||||
and print a configure status at the end.
|
|
||||||
* acinclude.m4 (GNUPG_BUILD_PROGRAM): New.
|
|
||||||
|
|
||||||
* scd/ : New. Added to Makefile and configure.
|
|
||||||
* configure.ac: Check for libopensc
|
|
||||||
* Makefile.am: Build scd only when libopensc is available
|
|
||||||
|
|
||||||
2002-01-23 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac (mkdtemp): See whether we have to provide a
|
|
||||||
replacement.
|
|
||||||
|
|
||||||
2001-12-18 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
Released 0.0.0.
|
|
||||||
|
|
||||||
2001-12-17 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* acinclude.m4: Add AM_PATH_LIBGCRYPT macro.
|
|
||||||
* configure.ac: and use it here. Figure out the location of libksba
|
|
||||||
|
|
||||||
2001-12-15 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac (missing_dir): Bail out if asprintf and fopencookie
|
|
||||||
are not available.
|
|
||||||
|
|
||||||
2001-12-04 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* configure.ac (HAVE_JNLIB_LOGGING): always define it.
|
|
||||||
|
|
||||||
|
|
||||||
Copyright 2001, 2002, 2004 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is free software; as a special exception the author gives
|
|
||||||
unlimited permission to copy and/or distribute it, with or without
|
|
||||||
modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
This file is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
|
||||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
|
|
229
INSTALL
229
INSTALL
@ -1,229 +0,0 @@
|
|||||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
|
|
||||||
Foundation, Inc.
|
|
||||||
|
|
||||||
This file is free documentation; the Free Software Foundation gives
|
|
||||||
unlimited permission to copy, distribute and modify it.
|
|
||||||
|
|
||||||
Basic Installation
|
|
||||||
==================
|
|
||||||
|
|
||||||
These are generic installation instructions.
|
|
||||||
|
|
||||||
The `configure' shell script attempts to guess correct values for
|
|
||||||
various system-dependent variables used during compilation. It uses
|
|
||||||
those values to create a `Makefile' in each directory of the package.
|
|
||||||
It may also create one or more `.h' files containing system-dependent
|
|
||||||
definitions. Finally, it creates a shell script `config.status' that
|
|
||||||
you can run in the future to recreate the current configuration, and a
|
|
||||||
file `config.log' containing compiler output (useful mainly for
|
|
||||||
debugging `configure').
|
|
||||||
|
|
||||||
It can also use an optional file (typically called `config.cache'
|
|
||||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
|
||||||
the results of its tests to speed up reconfiguring. (Caching is
|
|
||||||
disabled by default to prevent problems with accidental use of stale
|
|
||||||
cache files.)
|
|
||||||
|
|
||||||
If you need to do unusual things to compile the package, please try
|
|
||||||
to figure out how `configure' could check whether to do them, and mail
|
|
||||||
diffs or instructions to the address given in the `README' so they can
|
|
||||||
be considered for the next release. If you are using the cache, and at
|
|
||||||
some point `config.cache' contains results you don't want to keep, you
|
|
||||||
may remove or edit it.
|
|
||||||
|
|
||||||
The file `configure.ac' (or `configure.in') is used to create
|
|
||||||
`configure' by a program called `autoconf'. You only need
|
|
||||||
`configure.ac' if you want to change it or regenerate `configure' using
|
|
||||||
a newer version of `autoconf'.
|
|
||||||
|
|
||||||
The simplest way to compile this package is:
|
|
||||||
|
|
||||||
1. `cd' to the directory containing the package's source code and type
|
|
||||||
`./configure' to configure the package for your system. If you're
|
|
||||||
using `csh' on an old version of System V, you might need to type
|
|
||||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
|
||||||
`configure' itself.
|
|
||||||
|
|
||||||
Running `configure' takes awhile. While running, it prints some
|
|
||||||
messages telling which features it is checking for.
|
|
||||||
|
|
||||||
2. Type `make' to compile the package.
|
|
||||||
|
|
||||||
3. Optionally, type `make check' to run any self-tests that come with
|
|
||||||
the package.
|
|
||||||
|
|
||||||
4. Type `make install' to install the programs and any data files and
|
|
||||||
documentation.
|
|
||||||
|
|
||||||
5. You can remove the program binaries and object files from the
|
|
||||||
source code directory by typing `make clean'. To also remove the
|
|
||||||
files that `configure' created (so you can compile the package for
|
|
||||||
a different kind of computer), type `make distclean'. There is
|
|
||||||
also a `make maintainer-clean' target, but that is intended mainly
|
|
||||||
for the package's developers. If you use it, you may have to get
|
|
||||||
all sorts of other programs in order to regenerate files that came
|
|
||||||
with the distribution.
|
|
||||||
|
|
||||||
Compilers and Options
|
|
||||||
=====================
|
|
||||||
|
|
||||||
Some systems require unusual options for compilation or linking that
|
|
||||||
the `configure' script does not know about. Run `./configure --help'
|
|
||||||
for details on some of the pertinent environment variables.
|
|
||||||
|
|
||||||
You can give `configure' initial values for configuration parameters
|
|
||||||
by setting variables in the command line or in the environment. Here
|
|
||||||
is an example:
|
|
||||||
|
|
||||||
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
|
|
||||||
|
|
||||||
*Note Defining Variables::, for more details.
|
|
||||||
|
|
||||||
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 `..'.
|
|
||||||
|
|
||||||
If you have to use a `make' that does not support the `VPATH'
|
|
||||||
variable, you have to compile the package for one architecture at a
|
|
||||||
time in the source code directory. After you have installed the
|
|
||||||
package for one architecture, use `make distclean' before reconfiguring
|
|
||||||
for another architecture.
|
|
||||||
|
|
||||||
Installation Names
|
|
||||||
==================
|
|
||||||
|
|
||||||
By default, `make install' will install the package's files in
|
|
||||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
|
||||||
installation prefix other than `/usr/local' by giving `configure' the
|
|
||||||
option `--prefix=PATH'.
|
|
||||||
|
|
||||||
You can specify separate installation prefixes for
|
|
||||||
architecture-specific files and architecture-independent files. If you
|
|
||||||
give `configure' the option `--exec-prefix=PATH', the package will use
|
|
||||||
PATH as the prefix for installing programs and libraries.
|
|
||||||
Documentation and other data files will still use the regular prefix.
|
|
||||||
|
|
||||||
In addition, if you use an unusual directory layout you can give
|
|
||||||
options like `--bindir=PATH' to specify different values for particular
|
|
||||||
kinds of files. Run `configure --help' for a list of the directories
|
|
||||||
you can set and what kinds of files go in them.
|
|
||||||
|
|
||||||
If the package supports it, you can cause programs to be installed
|
|
||||||
with an extra prefix or suffix on their names by giving `configure' the
|
|
||||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
|
||||||
|
|
||||||
Optional Features
|
|
||||||
=================
|
|
||||||
|
|
||||||
Some packages pay attention to `--enable-FEATURE' options to
|
|
||||||
`configure', where FEATURE indicates an optional part of the package.
|
|
||||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
|
||||||
is something like `gnu-as' or `x' (for the X Window System). The
|
|
||||||
`README' should mention any `--enable-' and `--with-' options that the
|
|
||||||
package recognizes.
|
|
||||||
|
|
||||||
For packages that use the X Window System, `configure' can usually
|
|
||||||
find the X include and library files automatically, but if it doesn't,
|
|
||||||
you can use the `configure' options `--x-includes=DIR' and
|
|
||||||
`--x-libraries=DIR' to specify their locations.
|
|
||||||
|
|
||||||
Specifying the System Type
|
|
||||||
==========================
|
|
||||||
|
|
||||||
There may be some features `configure' cannot figure out
|
|
||||||
automatically, but needs to determine by the type of machine the package
|
|
||||||
will run on. Usually, assuming the package is built to be run on the
|
|
||||||
_same_ architectures, `configure' can figure that out, but if it prints
|
|
||||||
a message saying it cannot guess the machine type, give it the
|
|
||||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
|
||||||
type, such as `sun4', or a canonical name which has the form:
|
|
||||||
|
|
||||||
CPU-COMPANY-SYSTEM
|
|
||||||
|
|
||||||
where SYSTEM can have one of these forms:
|
|
||||||
|
|
||||||
OS KERNEL-OS
|
|
||||||
|
|
||||||
See the file `config.sub' for the possible values of each field. If
|
|
||||||
`config.sub' isn't included in this package, then this package doesn't
|
|
||||||
need to know the machine type.
|
|
||||||
|
|
||||||
If you are _building_ compiler tools for cross-compiling, you should
|
|
||||||
use the `--target=TYPE' option to select the type of system they will
|
|
||||||
produce code for.
|
|
||||||
|
|
||||||
If you want to _use_ a cross compiler, that generates code for a
|
|
||||||
platform different from the build platform, you should specify the
|
|
||||||
"host" platform (i.e., that on which the generated programs will
|
|
||||||
eventually be run) with `--host=TYPE'.
|
|
||||||
|
|
||||||
Sharing Defaults
|
|
||||||
================
|
|
||||||
|
|
||||||
If you want to set default values for `configure' scripts to share,
|
|
||||||
you can create a site shell script called `config.site' that gives
|
|
||||||
default values for variables like `CC', `cache_file', and `prefix'.
|
|
||||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
|
||||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
|
||||||
`CONFIG_SITE' environment variable to the location of the site script.
|
|
||||||
A warning: not all `configure' scripts look for a site script.
|
|
||||||
|
|
||||||
Defining Variables
|
|
||||||
==================
|
|
||||||
|
|
||||||
Variables not defined in a site shell script can be set in the
|
|
||||||
environment passed to `configure'. However, some packages may run
|
|
||||||
configure again during the build, and the customized values of these
|
|
||||||
variables may be lost. In order to avoid this problem, you should set
|
|
||||||
them in the `configure' command line, using `VAR=value'. For example:
|
|
||||||
|
|
||||||
./configure CC=/usr/local2/bin/gcc
|
|
||||||
|
|
||||||
will cause the specified gcc to be used as the C compiler (unless it is
|
|
||||||
overridden in the site shell script).
|
|
||||||
|
|
||||||
`configure' Invocation
|
|
||||||
======================
|
|
||||||
|
|
||||||
`configure' recognizes the following options to control how it
|
|
||||||
operates.
|
|
||||||
|
|
||||||
`--help'
|
|
||||||
`-h'
|
|
||||||
Print a summary of the options to `configure', and exit.
|
|
||||||
|
|
||||||
`--version'
|
|
||||||
`-V'
|
|
||||||
Print the version of Autoconf used to generate the `configure'
|
|
||||||
script, and exit.
|
|
||||||
|
|
||||||
`--cache-file=FILE'
|
|
||||||
Enable the cache: use and save the results of the tests in FILE,
|
|
||||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
|
||||||
disable caching.
|
|
||||||
|
|
||||||
`--config-cache'
|
|
||||||
`-C'
|
|
||||||
Alias for `--cache-file=config.cache'.
|
|
||||||
|
|
||||||
`--quiet'
|
|
||||||
`--silent'
|
|
||||||
`-q'
|
|
||||||
Do not print messages saying which checks are being made. To
|
|
||||||
suppress all normal output, redirect it to `/dev/null' (any error
|
|
||||||
messages will still be shown).
|
|
||||||
|
|
||||||
`--srcdir=DIR'
|
|
||||||
Look for the package's source code in directory DIR. Usually
|
|
||||||
`configure' can determine that directory automatically.
|
|
||||||
|
|
||||||
`configure' also accepts some other, not widely useful, options. Run
|
|
||||||
`configure --help' for more details.
|
|
||||||
|
|
64
Makefile.am
64
Makefile.am
@ -1,64 +0,0 @@
|
|||||||
# Makefile.am - main makefile for NewPG/GnuPG
|
|
||||||
# Copyright (C) 2001 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
|
|
||||||
|
|
||||||
## Process this file with automake to produce Makefile.in
|
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I m4
|
|
||||||
|
|
||||||
EXTRA_DIST = scripts/config.rpath autogen.sh README.CVS
|
|
||||||
DISTCLEANFILES = g10defs.h
|
|
||||||
|
|
||||||
if BUILD_GPG
|
|
||||||
gpg = g10
|
|
||||||
else
|
|
||||||
gpg =
|
|
||||||
endif
|
|
||||||
if BUILD_GPGSM
|
|
||||||
sm = sm
|
|
||||||
else
|
|
||||||
sm =
|
|
||||||
endif
|
|
||||||
if BUILD_AGENT
|
|
||||||
agent = agent
|
|
||||||
else
|
|
||||||
agent =
|
|
||||||
endif
|
|
||||||
if BUILD_SCDAEMON
|
|
||||||
scd = scd
|
|
||||||
else
|
|
||||||
scd =
|
|
||||||
endif
|
|
||||||
|
|
||||||
SUBDIRS = m4 intl jnlib common kbx \
|
|
||||||
${gpg} ${sm} ${agent} ${scd} tools po doc tests
|
|
||||||
|
|
||||||
dist-hook:
|
|
||||||
@set -e; \
|
|
||||||
for file in `cd $(top_srcdir); \
|
|
||||||
find scripts include -type f -name distfiles`; do \
|
|
||||||
dir=`dirname $$file` ; $(mkinstalldirs) $(distdir)/$$dir ; \
|
|
||||||
for i in distfiles `cat $(top_srcdir)/$$file` ; do \
|
|
||||||
ln $(top_srcdir)/$$dir/$$i $(distdir)/$$dir/$$i 2> /dev/null \
|
|
||||||
|| cp -p $(top_srcdir)/$$dir/$$i $(distdir)/$$dir/$$i; \
|
|
||||||
done ; \
|
|
||||||
done
|
|
||||||
echo "$(VERSION)" > $(distdir)/VERSION
|
|
||||||
|
|
||||||
|
|
||||||
|
|
171
NEWS
171
NEWS
@ -1,171 +0,0 @@
|
|||||||
Noteworthy changes in version 1.9.10
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 1.9.9 (2004-06-08)
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
* [gpg-agent] The new option --allow-mark-trusted is now required to
|
|
||||||
allow gpg-agent to add a key to the trustlist.txt after user
|
|
||||||
confirmation.
|
|
||||||
|
|
||||||
* Creating PKCS#10 requests does now honor the key usage.
|
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 1.9.8 (2004-04-29)
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
* [scdaemon] Overhauled the internal CCID driver.
|
|
||||||
|
|
||||||
* [scdaemon] Status files named ~/.gnupg/reader_<n>.status are now
|
|
||||||
written when using the internal CCID driver.
|
|
||||||
|
|
||||||
* [gpgsm] New commands --dump-{,secret,external}-keys to show a very
|
|
||||||
detailed view of the certificates.
|
|
||||||
|
|
||||||
* The keybox gets now compressed after 3 hours and ephemeral
|
|
||||||
stored certificates are deleted after about a day.
|
|
||||||
|
|
||||||
* [gpg] Usability fixes for --card-edit. Note, that this has already
|
|
||||||
been ported back to gnupg-1.3
|
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 1.9.7 (2004-04-06)
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
* Instrumented the modules for gpgconf.
|
|
||||||
|
|
||||||
* Added support for DINSIG card applications.
|
|
||||||
|
|
||||||
* Include the smimeCapabilities attribute with signed messages.
|
|
||||||
|
|
||||||
* Now uses the gettext domain "gnupg2" to avoid conflicts with gnupg
|
|
||||||
versions < 1.9.
|
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 1.9.6 (2004-03-06)
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
* Code cleanups and bug fixes.
|
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 1.9.5 (2004-02-21)
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
* gpg-protect-tool gets now installed into libexec as it ought to be.
|
|
||||||
Cleaned up the build system to better comply with the coding
|
|
||||||
standards.
|
|
||||||
|
|
||||||
* [gpgsm] The --import command is now able to autodetect pkcs#12
|
|
||||||
files and import secret and private keys from this file format.
|
|
||||||
A new command --export-secret-key-p12 is provided to allow
|
|
||||||
exporting of secret keys in PKCS\#12 format.
|
|
||||||
|
|
||||||
* [gpgsm] The pinentry will now present a description of the key for
|
|
||||||
whom the passphrase is requested.
|
|
||||||
|
|
||||||
* [gpgsm] New option --with-validation to check the validity of key
|
|
||||||
while listing it.
|
|
||||||
|
|
||||||
* New option --debug-level={none,basic,advanced,expert,guru} to map
|
|
||||||
the debug flags to sensitive levels on a per program base.
|
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 1.9.4 (2004-01-30)
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
* Added support for the Telesec NKS 2.0 card application.
|
|
||||||
|
|
||||||
* Added simple tool addgnupghome to create .gnupg directories from
|
|
||||||
/etc/skel/.gnupg.
|
|
||||||
|
|
||||||
* Various minor bug fixes and cleanups; mainly gpgsm and gpg-agent
|
|
||||||
related.
|
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 1.9.3 (2003-12-23)
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
* New gpgsm options --{enable,disable}-ocsp to validate keys using
|
|
||||||
OCSP. This option requires a not yet released DirMngr version.
|
|
||||||
Default is disabled.
|
|
||||||
|
|
||||||
* The --log-file option may now be used to print logs to a socket.
|
|
||||||
Prefix the socket name with "socket://" to enable this. This does
|
|
||||||
not work on all systems and falls back to stderr if there is a
|
|
||||||
problem with the socket.
|
|
||||||
|
|
||||||
* The options --encrypt-to and --no-encrypt-to now work the same in
|
|
||||||
gpgsm as in gpg. Note, they are also used in server mode.
|
|
||||||
|
|
||||||
* Duplicated recipients are now silently removed in gpgsm.
|
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 1.9.2 (2003-11-17)
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
* On card key generation is no longer done using the --gen-key
|
|
||||||
command but from the menu provided by the new --card-edit command.
|
|
||||||
|
|
||||||
* PINs are now properly cached and there are only 2 PINs visible.
|
|
||||||
The 3rd PIN (CHV2) is internally syncronized with the regular PIN.
|
|
||||||
|
|
||||||
* All kind of other internal stuff.
|
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 1.9.1 (2003-09-06)
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
* Support for OpenSC is back. scdaemon supports a --disable-opensc to
|
|
||||||
disable OpenSC use at runtime, so that PC/SC or ct-API can still be
|
|
||||||
used directly.
|
|
||||||
|
|
||||||
* Rudimentary support for the SCR335 smartcard reader using an
|
|
||||||
internal driver. Requires current libusb from CVS.
|
|
||||||
|
|
||||||
* Bug fixes.
|
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 1.9.0 (2003-08-05)
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
====== PLEASE SEE README-alpha =======
|
|
||||||
|
|
||||||
* gpg has been renamed to gpg2 and gpgv to gpgv2. This is a
|
|
||||||
temporary change to allow co-existing with stable gpg versions.
|
|
||||||
|
|
||||||
* ~/.gnupg/gpg.conf-1.9.0 is fist tried as config file before the
|
|
||||||
usual gpg.conf.
|
|
||||||
|
|
||||||
* Removed the -k, -kv and -kvv commands. -k is now an alias to
|
|
||||||
--list-keys. New command -K as alias for --list-secret-keys.
|
|
||||||
|
|
||||||
* Removed --run-as-shm-coprocess feature.
|
|
||||||
|
|
||||||
* gpg does now also use libgcrypt, libgpg-error is required.
|
|
||||||
|
|
||||||
* New gpgsm commands --call-dirmngr and --call-protect-tool.
|
|
||||||
|
|
||||||
* Changing a passphrase is now possible using "gpgsm --passwd"
|
|
||||||
|
|
||||||
* The content-type attribute is now recognized and created.
|
|
||||||
|
|
||||||
* The agent does now reread certain options on receiving a HUP.
|
|
||||||
|
|
||||||
* The pinentry is now forked for each request so that clients with
|
|
||||||
different environments are supported. When running in daemon mode
|
|
||||||
and --keep-display is not used the DISPLAY variable is ignored.
|
|
||||||
|
|
||||||
* Merged stuff from the newpg branch and started this new
|
|
||||||
development branch.
|
|
||||||
|
|
||||||
|
|
||||||
Copyright 2002, 2003 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is free software; as a special exception the author gives
|
|
||||||
unlimited permission to copy and/or distribute it, with or without
|
|
||||||
modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
This file is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
|
||||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
511
README
511
README
@ -1,511 +0,0 @@
|
|||||||
The GNU Privacy Guard 2
|
|
||||||
=========================
|
|
||||||
Version 1.9.x
|
|
||||||
|
|
||||||
|
|
||||||
GnuPG 1.9 is the future version of GnuPG; it is based on the gnupg-1.3
|
|
||||||
code and the previous newpg package. It will eventually lead to a
|
|
||||||
GnuPG 2.0 release. Note that GnuPG 1.3 and 1.9 are not always in sync
|
|
||||||
and thus features and bug fixes done in 1.3 are not necessary
|
|
||||||
available in 1.9.
|
|
||||||
|
|
||||||
|
|
||||||
BUILD INSTRUCTIONS
|
|
||||||
==================
|
|
||||||
|
|
||||||
GnuPG 1.9 depends on the following packages:
|
|
||||||
|
|
||||||
libgpg-error (ftp://ftp.gnupg.org/gcrypt/alpha/libgpg-error/)
|
|
||||||
libgcrypt (ftp://ftp.gnupg.org/gcrypt/alpha/libgcrypt/)
|
|
||||||
libassuan (ftp://ftp.gnupg.org/gcrypt/alpha/libassuan/)
|
|
||||||
libksba (ftp://ftp.gnupg.org/gcrypt/alpha/libksba/)
|
|
||||||
|
|
||||||
You also need the pinentry package for most function of GnupG; however
|
|
||||||
it is not a build requirement. pinentry is available at
|
|
||||||
ftp://ftp.gnupg.org/gcrypt/pinentry/ .
|
|
||||||
|
|
||||||
You should get the latest versions of course, the GnuPG configure
|
|
||||||
script complains if a version is not sufficient.
|
|
||||||
|
|
||||||
After building and installing the above packages in the order as given
|
|
||||||
above, you may now continue with GnupG installation (you may also just
|
|
||||||
try to build GnuPG to see whether your already installed versions are
|
|
||||||
sufficient).
|
|
||||||
|
|
||||||
As with all packages, you just have to do
|
|
||||||
|
|
||||||
./configure
|
|
||||||
make
|
|
||||||
make install
|
|
||||||
|
|
||||||
(Before doing install you might need to become root.)
|
|
||||||
|
|
||||||
If everything succeeds, you have a working GnuPG with support for
|
|
||||||
S/MIME and smartcards. Note that there is no binary gpg but a gpg2 so
|
|
||||||
that this package won't confict with a GnuPG 1.2 or1.3
|
|
||||||
installation. gpg2 behaves just like gpg and it is possible to symlink
|
|
||||||
oto gpg if you want to use gpg 1.9.
|
|
||||||
|
|
||||||
In case of problem please ask on gpa-dev@gnupg.org for advise. Note
|
|
||||||
that this release is only expected to build on GNU and *BSD systems.
|
|
||||||
|
|
||||||
A texinfo manual named `gnupg.info' will get installed. Some commands
|
|
||||||
and options given below. See also the section `SMARTCARD INTRO'.
|
|
||||||
|
|
||||||
|
|
||||||
COMMANDS
|
|
||||||
========
|
|
||||||
|
|
||||||
gpgsm:
|
|
||||||
------
|
|
||||||
|
|
||||||
--learn-card
|
|
||||||
|
|
||||||
Read information about the private keys from the smartcard and
|
|
||||||
import the certificates from there.
|
|
||||||
|
|
||||||
--export
|
|
||||||
|
|
||||||
Export all certificates stored in the Keybox or those specified on
|
|
||||||
the command line. When using --armor a few informational lines are
|
|
||||||
prepended before each block.
|
|
||||||
|
|
||||||
|
|
||||||
gpg2:
|
|
||||||
-----
|
|
||||||
|
|
||||||
--card-status
|
|
||||||
|
|
||||||
Show information pertaining smartcards implementing the OpenPGP
|
|
||||||
application.
|
|
||||||
|
|
||||||
--change-pin
|
|
||||||
|
|
||||||
Offers a menu to change the PIN of OpenPGP smartcards and to reset
|
|
||||||
the retry counters.
|
|
||||||
|
|
||||||
--card-edit
|
|
||||||
|
|
||||||
Offers a menu to change any data object on the card and to generate
|
|
||||||
the keys.
|
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
|
||||||
=======
|
|
||||||
|
|
||||||
gpgsm:
|
|
||||||
------
|
|
||||||
|
|
||||||
--include-certs <n>
|
|
||||||
|
|
||||||
Using N of -2 includes all certificate except for the Root cert,
|
|
||||||
-1 includes all certs, 0 does not include any certs, 1 includes only
|
|
||||||
the signers cert (this is the default) and all other positives
|
|
||||||
values include up to N certs starting with the signer cert.
|
|
||||||
|
|
||||||
--policy-file <filename>
|
|
||||||
|
|
||||||
Chnage the deault name of the policy file
|
|
||||||
|
|
||||||
--enable-policy-checks
|
|
||||||
--disable-policy-checks
|
|
||||||
|
|
||||||
By default policy checks are enabled. These options may be used to
|
|
||||||
change it.
|
|
||||||
|
|
||||||
--enable-crl-checks
|
|
||||||
--disable-crl-checks
|
|
||||||
|
|
||||||
By default the CRL checks are enabled and the DirMngr is used to
|
|
||||||
check for revoked certificates. The disable option is most useful
|
|
||||||
with a off-line connection to suppres this check.
|
|
||||||
|
|
||||||
--agent-program <path_to_agent_program>
|
|
||||||
|
|
||||||
Specify an agent program to be used for secret key operations. The
|
|
||||||
default value is "../agent/gpg-agent". This is only used as a
|
|
||||||
fallback when the envrionment varaibale GPG_AGENT_INFO is not set or
|
|
||||||
a running agent can't be connected.
|
|
||||||
|
|
||||||
--dirmngr-program <path_to_dirmgr_program>
|
|
||||||
|
|
||||||
Specify a dirmngr program to be used for CRL checks. The default
|
|
||||||
value is "/usr/sbin/dirmngr". This is only used as a fallback when
|
|
||||||
the environment varaibale DIRMNGR_INFO is not set or a running
|
|
||||||
dirmngr can't be connected.
|
|
||||||
|
|
||||||
--no-secmem-warning
|
|
||||||
|
|
||||||
Don't print the warning "no secure memory"
|
|
||||||
|
|
||||||
--armor
|
|
||||||
|
|
||||||
Create PEM ecoded output. Default is binary output.
|
|
||||||
|
|
||||||
--base64
|
|
||||||
|
|
||||||
Create Base-64 encoded output; i.e. PEM without the header lines.
|
|
||||||
|
|
||||||
--assume-armor
|
|
||||||
|
|
||||||
Assume the input data is PEM encoded. Default is to autodetect the
|
|
||||||
encoding but this is may fail.
|
|
||||||
|
|
||||||
--assume-base64
|
|
||||||
|
|
||||||
Assume the input data is plain base-64 encoded.
|
|
||||||
|
|
||||||
--assume-binary
|
|
||||||
|
|
||||||
Assume the input data is binary encoded.
|
|
||||||
|
|
||||||
--server
|
|
||||||
|
|
||||||
Run in server mode. This is used by GPGME to control gpgsm. See
|
|
||||||
the assuan specification regarding gpgsm about the used protocol.
|
|
||||||
Some options are ignored in server mode.
|
|
||||||
|
|
||||||
--local-user <user_id>
|
|
||||||
|
|
||||||
Set the user to be used for signing. The default is the first
|
|
||||||
secret key found in the database.
|
|
||||||
|
|
||||||
--with-key-data
|
|
||||||
|
|
||||||
Displays extra information with the --list-keys commands. Especially
|
|
||||||
a line tagged "grp" is printed which tells you the keygrip of a
|
|
||||||
key. This is string is for example used as the filename of the
|
|
||||||
secret key.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gpg-agent:
|
|
||||||
---------
|
|
||||||
|
|
||||||
--pinentry-program <path_to_pinentry_program>
|
|
||||||
|
|
||||||
Specify the PINentry program. The default value is
|
|
||||||
"<prefix>/bin/pinentry" so you most likely want to specify it.
|
|
||||||
|
|
||||||
--no-grab
|
|
||||||
|
|
||||||
Tell the pinentry not to grab keybourd and mouse. You most likely
|
|
||||||
want to give this option during testing and development to avoid
|
|
||||||
lockups in case of bugs.
|
|
||||||
|
|
||||||
|
|
||||||
scdaemon:
|
|
||||||
--------
|
|
||||||
|
|
||||||
--ctapi-driver <libraryname>
|
|
||||||
|
|
||||||
The default for Scdaemon is to use the PC/SC API currently provided
|
|
||||||
by libpcsclite.so. As an alternative the ctAPI can be used by
|
|
||||||
specify this option with the appropriate driver name
|
|
||||||
(e.g. libtowitoko.so).
|
|
||||||
|
|
||||||
--reader-port <portname>
|
|
||||||
|
|
||||||
This specifies the port of the chipcard reader. For PC/SC this is
|
|
||||||
currently ignored and the first PC/SC reader is used. For the
|
|
||||||
ctAPI, a number must be specified (the default is 32768 for the
|
|
||||||
first USB port).
|
|
||||||
|
|
||||||
--disable-ccid
|
|
||||||
|
|
||||||
Disable the integrated support for CCID compliant readers. This
|
|
||||||
allows to fall back to one of the other drivers even if the internal
|
|
||||||
CCID driver can handle the reader. Note, that CCID support is only
|
|
||||||
available if libusb was available at build time.
|
|
||||||
|
|
||||||
|
|
||||||
FILES
|
|
||||||
=====
|
|
||||||
|
|
||||||
The default home directory is ~/.gnupg. It can be changed by
|
|
||||||
either the --homedir option or by seting the environment variable
|
|
||||||
GNUPGHOME. This is a list of files usually found in this directory:
|
|
||||||
|
|
||||||
gpgsm.conf
|
|
||||||
|
|
||||||
Options for gpgsm. Options are the same as the command line
|
|
||||||
options but don't enter the leading dashes and give arguments
|
|
||||||
without an equal sign. Blank lines and lines starting with a
|
|
||||||
hash mark as the first non whitye space character are ignored.
|
|
||||||
|
|
||||||
gpg-agent.conf
|
|
||||||
|
|
||||||
Options for gpg-agent
|
|
||||||
|
|
||||||
scdaemon.conf
|
|
||||||
|
|
||||||
Options for scdaemon.
|
|
||||||
|
|
||||||
dirmngr.conf
|
|
||||||
|
|
||||||
Options for the DirMngr which is not part of this package and
|
|
||||||
the option file wilol most likely be moved to /etc
|
|
||||||
|
|
||||||
gpg.conf
|
|
||||||
|
|
||||||
Options for gpg. Note that old versions of gpg use the
|
|
||||||
filename `options' instead of `gpg.conf'.
|
|
||||||
|
|
||||||
gpg.conf-1.9.x
|
|
||||||
|
|
||||||
Options for gpg; tried before gpg.conf
|
|
||||||
|
|
||||||
|
|
||||||
policies.txt
|
|
||||||
|
|
||||||
A list of allowed CA policies. This file should give the
|
|
||||||
object identifiers of the policies line by line. Empty lines
|
|
||||||
and lines startung with a hash mark are ignored.
|
|
||||||
|
|
||||||
++++++++++
|
|
||||||
2.289.9.9
|
|
||||||
++++++++++
|
|
||||||
|
|
||||||
trustlist.txt
|
|
||||||
|
|
||||||
A list of trusted certificates usually maintained by
|
|
||||||
gpg-agent. It can however be edited manually. The file will
|
|
||||||
be created automagically with some explaining comments.
|
|
||||||
|
|
||||||
random_seed
|
|
||||||
|
|
||||||
Used internally for keeping the state of the RNG over
|
|
||||||
invocations.
|
|
||||||
|
|
||||||
pubring.kbx
|
|
||||||
|
|
||||||
The database file with the certificates.
|
|
||||||
|
|
||||||
pubring.gpg
|
|
||||||
|
|
||||||
The database file with the OpenPGP public keys. This will
|
|
||||||
eventually be merged with pubring.kbx
|
|
||||||
|
|
||||||
secring.gpg
|
|
||||||
|
|
||||||
The database file with the OpenPGP secret keys. This will be
|
|
||||||
removed when gpg is changed to make use of the gpg-agent.
|
|
||||||
|
|
||||||
|
|
||||||
private-keys-v1.d/
|
|
||||||
|
|
||||||
Directory holding the private keys maintained by gpg-agent.
|
|
||||||
For detailed info see agent/keyformat.txt. Note that there is
|
|
||||||
a helper tool gpg-protect-tool which may be used to protect or
|
|
||||||
unprotect keys. This is however nothing a user should care
|
|
||||||
about.
|
|
||||||
|
|
||||||
|
|
||||||
SOURCE FILES
|
|
||||||
============
|
|
||||||
|
|
||||||
Here is a list of directories with source files:
|
|
||||||
|
|
||||||
jnlib/ utility functions
|
|
||||||
kbx/ keybox library
|
|
||||||
g10/ the gpg program here called gpg2
|
|
||||||
sm/ the gpgsm program
|
|
||||||
agent/ the gpg-agent
|
|
||||||
scd/ the smartcard daemon
|
|
||||||
doc/ documentation
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
HOW TO SPECIFY A USER ID
|
|
||||||
========================
|
|
||||||
|
|
||||||
Due to the way X.509 certificates are made up we need a few new ways
|
|
||||||
to specify a certificate (aka key in OpenPGP). In addition to the
|
|
||||||
ways a user ID can be specified with gpg, I have implemented 3 new
|
|
||||||
modes for gpgsm, here is the entire list of ways to specify a key:
|
|
||||||
|
|
||||||
* By keyID.
|
|
||||||
|
|
||||||
This format is deducded from the length of the string and its
|
|
||||||
content or "0x" prefix. For use with OpenPGP a exclamation mark may
|
|
||||||
be appended to force use of the specified (sub)key.
|
|
||||||
|
|
||||||
As with v34 OpenPGP keys, the keyID of an X509 certificate are the
|
|
||||||
low 64 bits of the SHA-1 fingerprint. The use of keyIDs is just a
|
|
||||||
shortcut, for all automated processing the fingerprint should be
|
|
||||||
used.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
234567C4
|
|
||||||
0F34E556E
|
|
||||||
01347A56A
|
|
||||||
0xAB123456
|
|
||||||
|
|
||||||
234AABBCC34567C4
|
|
||||||
0F323456784E56EAB
|
|
||||||
01AB3FED1347A5612
|
|
||||||
0x234AABBCC34567C4
|
|
||||||
|
|
||||||
* By fingerprint
|
|
||||||
|
|
||||||
This is format is deduced from the length of the string and its
|
|
||||||
content or "0x" prefix. Note, that only the 20 byte fingerprint is
|
|
||||||
used with GPGSM (SHA-1 hash of the certificate). For use with
|
|
||||||
OpenPGP a exclamation mark may be appended to force use of the
|
|
||||||
specified (sub)key.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
1234343434343434C434343434343434
|
|
||||||
123434343434343C3434343434343734349A3434
|
|
||||||
0E12343434343434343434EAB3484343434343434
|
|
||||||
0xE12343434343434343434EAB3484343434343434
|
|
||||||
|
|
||||||
* Exact match on OpenPGP user ID
|
|
||||||
|
|
||||||
This is denoted by a leading equal sign. It does not make much
|
|
||||||
sense for X.509.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
=Heinrich Heine <heinrichh@uni-duesseldorf.de>
|
|
||||||
|
|
||||||
* Exact match on an email address.
|
|
||||||
|
|
||||||
This is indicated by enclosing the email address in the usual way
|
|
||||||
with left and right angles
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
<heinrichh@uni-duesseldorf.de>
|
|
||||||
|
|
||||||
* Word match
|
|
||||||
|
|
||||||
All words must match exactly (not case sensitive) but can appear in
|
|
||||||
any order in the user ID or a subjects name. Words are any
|
|
||||||
sequences of letters, digits, the underscore and all characters
|
|
||||||
with bit 7 set.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
+Heinrich Heine duesseldorf
|
|
||||||
|
|
||||||
* [NEW] Exact match by subject's DN
|
|
||||||
|
|
||||||
This is indicated by a leading slash, directly followed by the
|
|
||||||
rfc2253 encoded DN of the subject. Note that you can't use the
|
|
||||||
string printed by "gpgsm --list-keys" because that one as been
|
|
||||||
reordered and modified for better readability; use --with-colons to
|
|
||||||
print the raw (but standard escaped) rfc2253 string
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
/CN=Heinrich Heine,O=Poets,L=Paris,C=FR
|
|
||||||
|
|
||||||
* [NEW] Excact match by issuer's DN
|
|
||||||
|
|
||||||
This is indicated by a leading hash mark, directly followed by a
|
|
||||||
slash and then directly followed by the rfc2253 encoded DN of the
|
|
||||||
issuer. This should return the Root cert of the issuer. See note
|
|
||||||
above.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
#/CN=Root Cert,O=Poets,L=Paris,C=FR
|
|
||||||
|
|
||||||
* [NEW] Exact match by serial number and subject's DN
|
|
||||||
|
|
||||||
This is indicated by a hash mark, followed by the hexadecmal
|
|
||||||
representation of the serial number, the followed by a slahs and
|
|
||||||
the RFC2253 encoded DN of the issuer. See note above.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
#4F03/CN=Root Cert,O=Poets,L=Paris,C=FR
|
|
||||||
|
|
||||||
* Substring match
|
|
||||||
|
|
||||||
By case insensitive substring matching. This is the default mode
|
|
||||||
but applications may want to explicitly indicate this by putting
|
|
||||||
the asterisk in front.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
Heine
|
|
||||||
*Heine
|
|
||||||
|
|
||||||
|
|
||||||
Please note that we have reused the hash mark indentifier which was
|
|
||||||
used in old GnuPG versions to indicate the so called local-id. It is
|
|
||||||
not anymore used and there should be no conflict when used with X.509
|
|
||||||
stuff.
|
|
||||||
|
|
||||||
Using the rfc2253 format of DNs has the drawback that it is not
|
|
||||||
possible to map them back to the original encoding, however we don't
|
|
||||||
have to do this, because our key database stores this encoding as meta
|
|
||||||
data.
|
|
||||||
|
|
||||||
Some of the search modes are not yet implemented ;-)
|
|
||||||
|
|
||||||
|
|
||||||
HOW TO IMPORT A PRIVATE KEY
|
|
||||||
===========================
|
|
||||||
There is some limited support to import a private key from a PKCS-12
|
|
||||||
file.
|
|
||||||
|
|
||||||
gpgsm --import foo.p12
|
|
||||||
|
|
||||||
This require that the gpg-agent is running.
|
|
||||||
|
|
||||||
|
|
||||||
HOW TO EXPORT A PRIVATE KEY
|
|
||||||
===========================
|
|
||||||
There is also limited support to export a private key in PKCS-12
|
|
||||||
format. However the certificate is not stored and there is no MAC applied.
|
|
||||||
|
|
||||||
gpgsm --call-protect-tool --p12-export foo.key >foo.p12
|
|
||||||
|
|
||||||
|
|
||||||
SMARTCARD INTRO
|
|
||||||
===============
|
|
||||||
|
|
||||||
GPG, the OpenPGP part of GnuPG, supports the OpenPGP smartcard
|
|
||||||
(surprise!); see http://g10code.com/p-card.html.
|
|
||||||
|
|
||||||
[Fixme: We need to explain this further]
|
|
||||||
|
|
||||||
|
|
||||||
GPGSM, the CMS (S/MIME) part of GnuPG, supports two kinds of
|
|
||||||
smartcards. The most flexible way is to use PKCS#15 compliant cards,
|
|
||||||
however you must have build GnuPG with support for the OpenSC library.
|
|
||||||
The build process automagically detects the presence of this library
|
|
||||||
and will include support for these cards.
|
|
||||||
|
|
||||||
The other card we currently support is the Telesec NetKey card with
|
|
||||||
the NKS 2.0 card application.
|
|
||||||
|
|
||||||
Before GPGSM can make use of a new card it must gather some
|
|
||||||
information, like the card's serial number, the public keys and the
|
|
||||||
certificates stored on the card. Thus for a new card you need to run
|
|
||||||
the command
|
|
||||||
|
|
||||||
gpgsm --learn-card
|
|
||||||
|
|
||||||
once. This is also a good test to see whether your card reader is
|
|
||||||
properly installed. See below in case of error. Once this has been
|
|
||||||
done you may use the keys stored on the card in the same way you use
|
|
||||||
keys stored on the disk. gpgsm automagically knows whether a card is
|
|
||||||
required and will pop up the pinentry to ask you to insert the
|
|
||||||
correct card.
|
|
||||||
|
|
||||||
For selecting the driver, see the options of scdaemon. A useful
|
|
||||||
debugging flag is "--debug 2048" showing the communication between
|
|
||||||
scdaemon and the reader.
|
|
||||||
|
|
||||||
[fixme: write more stuff]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
51
README.CVS
51
README.CVS
@ -1,51 +0,0 @@
|
|||||||
If you are building from CVS, run the script
|
|
||||||
|
|
||||||
./autogen.sh
|
|
||||||
|
|
||||||
first, to make sure that you have all the necessary maintainer tools
|
|
||||||
are installed and to build the actual configuration files. Then run
|
|
||||||
|
|
||||||
./configure --enable-maintainer-mode
|
|
||||||
|
|
||||||
followed by the usual make.
|
|
||||||
|
|
||||||
If autogen.sh complains about insufficient versions of the required
|
|
||||||
tools, or the tools are not installed, you may use environment
|
|
||||||
variables to override the default tool names:
|
|
||||||
|
|
||||||
AUTOMAKE_SUFFIX is used as a suffix for all tools from the automake
|
|
||||||
package. For example
|
|
||||||
AUTOMAKE_SUFFIX="-1.7" ./autogen.sh
|
|
||||||
uses "automake-1.7" and "aclocal-1.7.
|
|
||||||
AUTOMAKE_PREFIX is used as a prefix for all tools from the automake
|
|
||||||
page and may be combined with AUTOMAKE_SUFFIX. e.g.:
|
|
||||||
AUTOMAKE_PREFIX=/usr/foo/bin ./autogen.sh
|
|
||||||
uses "automake" and "aclocal" in the /usr/foo/bin
|
|
||||||
directory.
|
|
||||||
AUTOCONF_SUFFIX is used as a suffix for all tools from the automake
|
|
||||||
package
|
|
||||||
AUTOCONF_PREFIX is used as a prefix for all tools from the automake
|
|
||||||
package
|
|
||||||
GETTEXT_SUFFIX is used as a suffix for all tools from the gettext
|
|
||||||
package
|
|
||||||
GETTEXT_PREFIX is used as a prefix for all tools from the gettext
|
|
||||||
package
|
|
||||||
|
|
||||||
It is also possible to use the variable name AUTOMAKE, AUTOCONF,
|
|
||||||
ACLOCAL, AUTOHEADER, GETTEXT and MSGMERGE to directly specify the name
|
|
||||||
of the programs to run. It is however better to use the suffix and
|
|
||||||
prefix forms as described above because that does not require
|
|
||||||
knowledge about the actual tools used by autgen.sh.
|
|
||||||
|
|
||||||
|
|
||||||
Please don't use autopoint, libtoolize or autoreconf unless you are
|
|
||||||
the current maintainer and want to update the standard configuration
|
|
||||||
files. All those files should be in the CVS and only updated manually
|
|
||||||
if the maintainer decides that newer versions are required. The
|
|
||||||
maintainer should also make sure that the required version of automake
|
|
||||||
et al. are properly indicated at the top of configure.ac and take care
|
|
||||||
to copy the files and not merely use symlinks.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
5
THANKS
5
THANKS
@ -1,5 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
Richard Lefebvre rick at CERCA.UMontreal.CA
|
|
||||||
Andrew J. Schorr aschorr at telemetry-investments.com
|
|
||||||
Michael Nottebrock michaelnottebrock at gmx.net
|
|
78
TODO
78
TODO
@ -1,78 +0,0 @@
|
|||||||
-*- outline -*-
|
|
||||||
|
|
||||||
* src/base64
|
|
||||||
** Make parsing more robust
|
|
||||||
Currently we don't cope with overlong lines in the best way.
|
|
||||||
|
|
||||||
* sm/call-agent.c
|
|
||||||
** The protocol uses an incomplete S-expression
|
|
||||||
We should always use valid S-Exp and not just parts.
|
|
||||||
** Some code should go into import.c
|
|
||||||
** When we allow concurrent service request in gpgsm, we
|
|
||||||
might want to have an agent context for each service request
|
|
||||||
(i.e. Assuan context).
|
|
||||||
|
|
||||||
* sm/certreqgen.c
|
|
||||||
** Improve error reporting
|
|
||||||
** Do some basic checks on the supplied DNs
|
|
||||||
|
|
||||||
* sm/certchain.c
|
|
||||||
** When a certificate chain was sucessfully verified, make ephemeral certs used in this chain permanent.
|
|
||||||
** figure out how to auto retrieve a key by serialno+issuer.
|
|
||||||
Dirmngr is currently not able to parse more than the CN.
|
|
||||||
|
|
||||||
* sm/decrypt.c
|
|
||||||
** replace leading zero in integer hack by a cleaner solution
|
|
||||||
|
|
||||||
* sm/gpgsm.c
|
|
||||||
** Support --output for all commands
|
|
||||||
** mark all unimplemented commands and options.
|
|
||||||
** Print a hint when MD2 is the cause for a problem.
|
|
||||||
** Implement --default-key
|
|
||||||
** Using --export-secret-key-p12 with a non-pth agent
|
|
||||||
This leads to a lockup because gpgsm is still accessing the agent
|
|
||||||
while gpg-protect-tool wants to pop up the pinentry. Solution is
|
|
||||||
to release the connection. This is not trivial, thus we are going
|
|
||||||
to do that while changing gpgsm to allow concurrent operations.
|
|
||||||
|
|
||||||
* sm/keydb.c
|
|
||||||
** Check file permissions
|
|
||||||
** Check that all error code mapping is done.
|
|
||||||
** Remove the inter-module dependencies between gpgsm and keybox
|
|
||||||
** Add an source_of_key field
|
|
||||||
|
|
||||||
* agent/gpg-agent.c
|
|
||||||
** A SIGHUP should also restart the scdaemon
|
|
||||||
But do this only after all connections terminated.
|
|
||||||
As of now we only send a RESET.
|
|
||||||
|
|
||||||
* agent/command.c
|
|
||||||
** Make sure that secure memory is used where appropriate
|
|
||||||
|
|
||||||
* agent/pkdecrypt.c, agent/pksign.c
|
|
||||||
** Don't use stdio to return results.
|
|
||||||
|
|
||||||
* agent/divert-scd.c
|
|
||||||
Remove the agent_reset_scd kludge.
|
|
||||||
|
|
||||||
* Move pkcs-1 encoding into libgcrypt.
|
|
||||||
|
|
||||||
* Use a MAC to protect some files.
|
|
||||||
|
|
||||||
* sm/export.c
|
|
||||||
** Return an error code or a status info per user ID.
|
|
||||||
|
|
||||||
* Where is http.c, regcomp.c, srv.c, w32reg.c ?
|
|
||||||
|
|
||||||
* scd/sc-investigate
|
|
||||||
** Enhance with card compatibility check
|
|
||||||
|
|
||||||
* tests
|
|
||||||
** Makefile.am
|
|
||||||
We use printf(1) to setup the library path, this is not portable.
|
|
||||||
Furthermore LD_LIBRARY_PATH is not used on all systems. It doesn't
|
|
||||||
matter for now, because we use some GNU/*BSDish features anyway.
|
|
||||||
|
|
||||||
** Add a test to check the extkeyusage.
|
|
||||||
|
|
||||||
|
|
436
acinclude.m4
436
acinclude.m4
@ -1,436 +0,0 @@
|
|||||||
dnl macros to configure gnupg
|
|
||||||
dnl Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
|
|
||||||
dnl
|
|
||||||
dnl This file is part of GnuPG.
|
|
||||||
dnl
|
|
||||||
dnl GnuPG is free software; you can redistribute it and/or modify
|
|
||||||
dnl it under the terms of the GNU General Public License as published by
|
|
||||||
dnl the Free Software Foundation; either version 2 of the License, or
|
|
||||||
dnl (at your option) any later version.
|
|
||||||
dnl
|
|
||||||
dnl GnuPG is distributed in the hope that it will be useful,
|
|
||||||
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
dnl GNU General Public License for more details.
|
|
||||||
dnl
|
|
||||||
dnl You should have received a copy of the GNU General Public License
|
|
||||||
dnl along with this program; if not, write to the Free Software
|
|
||||||
dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
||||||
|
|
||||||
dnl GNUPG_CHECK_TYPEDEF(TYPE, HAVE_NAME)
|
|
||||||
dnl Check whether a typedef exists and create a #define $2 if it exists
|
|
||||||
dnl
|
|
||||||
AC_DEFUN(GNUPG_CHECK_TYPEDEF,
|
|
||||||
[ AC_MSG_CHECKING(for $1 typedef)
|
|
||||||
AC_CACHE_VAL(gnupg_cv_typedef_$1,
|
|
||||||
[AC_TRY_COMPILE([#define _GNU_SOURCE 1
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/types.h>], [
|
|
||||||
#undef $1
|
|
||||||
int a = sizeof($1);
|
|
||||||
], gnupg_cv_typedef_$1=yes, gnupg_cv_typedef_$1=no )])
|
|
||||||
AC_MSG_RESULT($gnupg_cv_typedef_$1)
|
|
||||||
if test "$gnupg_cv_typedef_$1" = yes; then
|
|
||||||
AC_DEFINE($2,1,[Defined if a `]$1[' is typedef'd])
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
dnl GNUPG_CHECK_GNUMAKE
|
|
||||||
dnl
|
|
||||||
AC_DEFUN(GNUPG_CHECK_GNUMAKE,
|
|
||||||
[
|
|
||||||
if ${MAKE-make} --version 2>/dev/null | grep '^GNU ' >/dev/null 2>&1; then
|
|
||||||
:
|
|
||||||
else
|
|
||||||
AC_MSG_WARN([[
|
|
||||||
***
|
|
||||||
*** It seems that you are not using GNU make. Some make tools have serious
|
|
||||||
*** flaws and you may not be able to build this software at all. Before you
|
|
||||||
*** complain, please try GNU make: GNU make is easy to build and available
|
|
||||||
*** at all GNU archives. It is always available from ftp.gnu.org:/gnu/make.
|
|
||||||
***]])
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
||||||
dnl GNUPG_CHECK_FAQPROG
|
|
||||||
dnl
|
|
||||||
AC_DEFUN(GNUPG_CHECK_FAQPROG,
|
|
||||||
[ AC_MSG_CHECKING(for faqprog.pl)
|
|
||||||
if faqprog.pl -V 2>/dev/null | grep '^faqprog.pl ' >/dev/null 2>&1; then
|
|
||||||
working_faqprog=yes
|
|
||||||
FAQPROG="faqprog.pl"
|
|
||||||
else
|
|
||||||
working_faqprog=no
|
|
||||||
FAQPROG=": "
|
|
||||||
fi
|
|
||||||
AC_MSG_RESULT($working_faqprog)
|
|
||||||
AC_SUBST(FAQPROG)
|
|
||||||
AM_CONDITIONAL(WORKING_FAQPROG, test "$working_faqprog" = "yes" )
|
|
||||||
|
|
||||||
dnl if test $working_faqprog = no; then
|
|
||||||
dnl AC_MSG_WARN([[
|
|
||||||
dnl ***
|
|
||||||
dnl *** It seems that the faqprog.pl program is not installed;
|
|
||||||
dnl *** however it is only needed if you want to change the FAQ.
|
|
||||||
dnl *** (faqprog.pl should be available at:
|
|
||||||
dnl *** ftp://ftp.gnupg.org/gcrypt/contrib/faqprog.pl )
|
|
||||||
dnl *** No need to worry about this warning.
|
|
||||||
dnl ***]])
|
|
||||||
dnl fi
|
|
||||||
])
|
|
||||||
|
|
||||||
dnl GNUPG_CHECK_DOCBOOK_TO_TEXI
|
|
||||||
dnl
|
|
||||||
AC_DEFUN(GNUPG_CHECK_DOCBOOK_TO_TEXI,
|
|
||||||
[
|
|
||||||
AC_CHECK_PROG(DOCBOOK_TO_TEXI, docbook2texi, yes, no)
|
|
||||||
AC_MSG_CHECKING(for sgml to texi tools)
|
|
||||||
working_sgmltotexi=no
|
|
||||||
if test "$ac_cv_prog_DOCBOOK_TO_TEXI" = yes; then
|
|
||||||
if sgml2xml -v /dev/null 2>&1 | grep 'SP version' >/dev/null 2>&1 ; then
|
|
||||||
working_sgmltotexi=yes
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AC_MSG_RESULT($working_sgmltotexi)
|
|
||||||
AM_CONDITIONAL(HAVE_DOCBOOK_TO_TEXI, test "$working_sgmltotexi" = "yes" )
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dnl GNUPG_CHECK_ENDIAN
|
|
||||||
dnl define either LITTLE_ENDIAN_HOST or BIG_ENDIAN_HOST
|
|
||||||
dnl
|
|
||||||
define(GNUPG_CHECK_ENDIAN,
|
|
||||||
[
|
|
||||||
tmp_assumed_endian=big
|
|
||||||
if test "$cross_compiling" = yes; then
|
|
||||||
case "$host_cpu" in
|
|
||||||
i@<:@345678@:>@* )
|
|
||||||
tmp_assumed_endian=little
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
AC_MSG_WARN(cross compiling; assuming $tmp_assumed_endian endianess)
|
|
||||||
fi
|
|
||||||
AC_MSG_CHECKING(endianess)
|
|
||||||
AC_CACHE_VAL(gnupg_cv_c_endian,
|
|
||||||
[ gnupg_cv_c_endian=unknown
|
|
||||||
# See if sys/param.h defines the BYTE_ORDER macro.
|
|
||||||
AC_TRY_COMPILE([#include <sys/types.h>
|
|
||||||
#include <sys/param.h>], [
|
|
||||||
#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
|
|
||||||
bogus endian macros
|
|
||||||
#endif], [# It does; now see whether it defined to BIG_ENDIAN or not.
|
|
||||||
AC_TRY_COMPILE([#include <sys/types.h>
|
|
||||||
#include <sys/param.h>], [
|
|
||||||
#if BYTE_ORDER != BIG_ENDIAN
|
|
||||||
not big endian
|
|
||||||
#endif], gnupg_cv_c_endian=big, gnupg_cv_c_endian=little)])
|
|
||||||
if test "$gnupg_cv_c_endian" = unknown; then
|
|
||||||
AC_TRY_RUN([main () {
|
|
||||||
/* Are we little or big endian? From Harbison&Steele. */
|
|
||||||
union
|
|
||||||
{
|
|
||||||
long l;
|
|
||||||
char c[sizeof (long)];
|
|
||||||
} u;
|
|
||||||
u.l = 1;
|
|
||||||
exit (u.c[sizeof (long) - 1] == 1);
|
|
||||||
}],
|
|
||||||
gnupg_cv_c_endian=little,
|
|
||||||
gnupg_cv_c_endian=big,
|
|
||||||
gnupg_cv_c_endian=$tmp_assumed_endian
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
AC_MSG_RESULT([$gnupg_cv_c_endian])
|
|
||||||
if test "$gnupg_cv_c_endian" = little; then
|
|
||||||
AC_DEFINE(LITTLE_ENDIAN_HOST,1,
|
|
||||||
[Defined if the host has little endian byte ordering])
|
|
||||||
else
|
|
||||||
AC_DEFINE(BIG_ENDIAN_HOST,1,
|
|
||||||
[Defined if the host has big endian byte ordering])
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Check for the getsockopt SO_PEERCRED
|
|
||||||
AC_DEFUN(GNUPG_SYS_SO_PEERCRED,
|
|
||||||
[ AC_MSG_CHECKING(for SO_PEERCRED)
|
|
||||||
AC_CACHE_VAL(gnupg_cv_sys_so_peercred,
|
|
||||||
[AC_TRY_COMPILE([#include <sys/socket.h>],
|
|
||||||
[struct ucred cr;
|
|
||||||
int cl = sizeof cr;
|
|
||||||
getsockopt (1, SOL_SOCKET, SO_PEERCRED, &cr, &cl);],
|
|
||||||
gnupg_cv_sys_so_peercred=yes,
|
|
||||||
gnupg_cv_sys_so_peercred=no)
|
|
||||||
])
|
|
||||||
AC_MSG_RESULT($gnupg_cv_sys_so_peercred)
|
|
||||||
if test $gnupg_cv_sys_so_peercred = yes; then
|
|
||||||
AC_DEFINE(HAVE_SO_PEERCRED, 1,
|
|
||||||
[Defined if SO_PEERCRED is supported (Linux)])
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# GNUPG_BUILD_PROGRAM(NAME,DEFAULT)
|
|
||||||
# Add a --enable-NAME option to configure an set the
|
|
||||||
# shell variable build_NAME either to "yes" or "no". DEFAULT must
|
|
||||||
# either be "yes" or "no" and decided on the default value for
|
|
||||||
# build_NAME and whether --enable-NAME or --disable-NAME is shown with
|
|
||||||
# ./configure --help
|
|
||||||
AC_DEFUN(GNUPG_BUILD_PROGRAM,
|
|
||||||
[build_$1=$2
|
|
||||||
m4_if([$2],[yes],[
|
|
||||||
AC_ARG_ENABLE([$1], AC_HELP_STRING([--disable-$1],
|
|
||||||
[do not build the $1 program]),
|
|
||||||
build_$1=$enableval, build_$1=$2)
|
|
||||||
],[
|
|
||||||
AC_ARG_ENABLE([$1], AC_HELP_STRING([--enable-$1],
|
|
||||||
[build the $1 program]),
|
|
||||||
build_$1=$enableval, build_$1=$2)
|
|
||||||
])
|
|
||||||
case "$build_$1" in
|
|
||||||
no|yes)
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
AC_MSG_ERROR([only yes or no allowed for feature --enable-$1])
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# GNUPG_PTH_VERSION_CHECK(REQUIRED)
|
|
||||||
#
|
|
||||||
# If the version is sufficient, HAVE_PTH will be set to yes.
|
|
||||||
#
|
|
||||||
# Taken form the m4 macros which come with Pth
|
|
||||||
AC_DEFUN(GNUPG_PTH_VERSION_CHECK,
|
|
||||||
[
|
|
||||||
_pth_version=`$PTH_CONFIG --version | awk 'NR==1 {print [$]3}'`
|
|
||||||
_req_version="ifelse([$1],,1.2.0,$1)"
|
|
||||||
for _var in _pth_version _req_version; do
|
|
||||||
eval "_val=\"\$${_var}\""
|
|
||||||
_major=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\1/'`
|
|
||||||
_minor=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\2/'`
|
|
||||||
_rtype=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\3/'`
|
|
||||||
_micro=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\4/'`
|
|
||||||
case $_rtype in
|
|
||||||
"a" ) _rtype=0 ;;
|
|
||||||
"b" ) _rtype=1 ;;
|
|
||||||
"." ) _rtype=2 ;;
|
|
||||||
esac
|
|
||||||
_hex=`echo dummy | awk '{ printf("%d%02d%1d%02d", major, minor, rtype, micro); }' \
|
|
||||||
"major=$_major" "minor=$_minor" "rtype=$_rtype" "micro=$_micro"`
|
|
||||||
eval "${_var}_hex=\"\$_hex\""
|
|
||||||
done
|
|
||||||
have_pth=no
|
|
||||||
if test ".$_pth_version_hex" != .; then
|
|
||||||
if test ".$_req_version_hex" != .; then
|
|
||||||
if test $_pth_version_hex -ge $_req_version_hex; then
|
|
||||||
have_pth=yes
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if test $have_pth = no; then
|
|
||||||
AC_MSG_WARN([[
|
|
||||||
***
|
|
||||||
*** Found Pth version $_pth_version, but require at least
|
|
||||||
*** version $_req_version. Please upgrade Pth first.
|
|
||||||
***]])
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
# Check whether mlock is broken (hpux 10.20 raises a SIGBUS if mlock
|
|
||||||
# is not called from uid 0 (not tested whether uid 0 works)
|
|
||||||
# For DECs Tru64 we have also to check whether mlock is in librt
|
|
||||||
# mlock is there a macro using memlk()
|
|
||||||
dnl GNUPG_CHECK_MLOCK
|
|
||||||
dnl
|
|
||||||
define(GNUPG_CHECK_MLOCK,
|
|
||||||
[ AC_CHECK_FUNCS(mlock)
|
|
||||||
if test "$ac_cv_func_mlock" = "no"; then
|
|
||||||
AC_CHECK_HEADERS(sys/mman.h)
|
|
||||||
if test "$ac_cv_header_sys_mman_h" = "yes"; then
|
|
||||||
# Add librt to LIBS:
|
|
||||||
AC_CHECK_LIB(rt, memlk)
|
|
||||||
AC_CACHE_CHECK([whether mlock is in sys/mman.h],
|
|
||||||
gnupg_cv_mlock_is_in_sys_mman,
|
|
||||||
[AC_TRY_LINK([
|
|
||||||
#include <assert.h>
|
|
||||||
#ifdef HAVE_SYS_MMAN_H
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#endif
|
|
||||||
], [
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* glibc defines this for functions which it implements
|
|
||||||
* to always fail with ENOSYS. Some functions are actually
|
|
||||||
* named something starting with __ and the normal name
|
|
||||||
* is an alias. */
|
|
||||||
#if defined (__stub_mlock) || defined (__stub___mlock)
|
|
||||||
choke me
|
|
||||||
#else
|
|
||||||
mlock(&i, 4);
|
|
||||||
#endif
|
|
||||||
; return 0;
|
|
||||||
],
|
|
||||||
gnupg_cv_mlock_is_in_sys_mman=yes,
|
|
||||||
gnupg_cv_mlock_is_in_sys_mman=no)])
|
|
||||||
if test "$gnupg_cv_mlock_is_in_sys_mman" = "yes"; then
|
|
||||||
AC_DEFINE(HAVE_MLOCK,1,
|
|
||||||
[Defined if the system supports an mlock() call])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if test "$ac_cv_func_mlock" = "yes"; then
|
|
||||||
AC_MSG_CHECKING(whether mlock is broken)
|
|
||||||
AC_CACHE_VAL(gnupg_cv_have_broken_mlock,
|
|
||||||
AC_TRY_RUN([
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
char *pool;
|
|
||||||
int err;
|
|
||||||
long int pgsize = getpagesize();
|
|
||||||
|
|
||||||
pool = malloc( 4096 + pgsize );
|
|
||||||
if( !pool )
|
|
||||||
return 2;
|
|
||||||
pool += (pgsize - ((long int)pool % pgsize));
|
|
||||||
|
|
||||||
err = mlock( pool, 4096 );
|
|
||||||
if( !err || errno == EPERM )
|
|
||||||
return 0; /* okay */
|
|
||||||
|
|
||||||
return 1; /* hmmm */
|
|
||||||
}
|
|
||||||
|
|
||||||
],
|
|
||||||
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,1,
|
|
||||||
[Defined if the mlock() call does not work])
|
|
||||||
AC_MSG_RESULT(yes)
|
|
||||||
AC_CHECK_FUNCS(plock)
|
|
||||||
else
|
|
||||||
if test "$gnupg_cv_have_broken_mlock" = "no"; then
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT(assuming no)
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
dnl Stolen from gcc
|
|
||||||
dnl Define MKDIR_TAKES_ONE_ARG if mkdir accepts only one argument instead
|
|
||||||
dnl of the usual 2.
|
|
||||||
AC_DEFUN(GNUPG_FUNC_MKDIR_TAKES_ONE_ARG,
|
|
||||||
[AC_CHECK_HEADERS(sys/stat.h unistd.h direct.h)
|
|
||||||
AC_CACHE_CHECK([if mkdir takes one argument], gnupg_cv_mkdir_takes_one_arg,
|
|
||||||
[AC_TRY_COMPILE([
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifdef HAVE_SYS_STAT_H
|
|
||||||
# include <sys/stat.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_UNISTD_H
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_DIRECT_H
|
|
||||||
# include <direct.h>
|
|
||||||
#endif], [mkdir ("foo", 0);],
|
|
||||||
gnupg_cv_mkdir_takes_one_arg=no, gnupg_cv_mkdir_takes_one_arg=yes)])
|
|
||||||
if test $gnupg_cv_mkdir_takes_one_arg = yes ; then
|
|
||||||
AC_DEFINE(MKDIR_TAKES_ONE_ARG,1,
|
|
||||||
[Defined if mkdir() does not take permission flags])
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dnl AM_PATH_OPENSC([MINIMUM-VERSION,
|
|
||||||
dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
|
|
||||||
dnl Test for OpenSC and define OPENSC_CFLAGS and OPENSC_LIBS
|
|
||||||
dnl
|
|
||||||
AC_DEFUN(AM_PATH_OPENSC,
|
|
||||||
[ AC_ARG_WITH(opensc-prefix,
|
|
||||||
AC_HELP_STRING([--with-opensc-prefix=PFX],
|
|
||||||
[prefix where OpenSC is installed (optional)]),
|
|
||||||
opensc_config_prefix="$withval", opensc_config_prefix="")
|
|
||||||
if test x$opensc_config_prefix != x ; then
|
|
||||||
opensc_config_args="$opensc_config_args --prefix=$opensc_config_prefix"
|
|
||||||
if test x${OPENSC_CONFIG+set} != xset ; then
|
|
||||||
OPENSC_CONFIG=$opensc_config_prefix/bin/opensc-config
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_PATH_PROG(OPENSC_CONFIG, opensc-config, no)
|
|
||||||
min_opensc_version=ifelse([$1], ,0.7.0,$1)
|
|
||||||
AC_MSG_CHECKING(for OpenSC - version >= $min_opensc_version)
|
|
||||||
ok=no
|
|
||||||
if test "$OPENSC_CONFIG" != "no" ; then
|
|
||||||
req_major=`echo $min_opensc_version | \
|
|
||||||
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
|
|
||||||
req_minor=`echo $min_opensc_version | \
|
|
||||||
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
|
|
||||||
req_micro=`echo $min_opensc_version | \
|
|
||||||
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
|
|
||||||
opensc_config_version=`$OPENSC_CONFIG $opensc_config_args --version 2>/dev/null || echo 0.0.0`
|
|
||||||
major=`echo $opensc_config_version | \
|
|
||||||
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
|
|
||||||
minor=`echo $opensc_config_version | \
|
|
||||||
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
|
|
||||||
micro=`echo $opensc_config_version | \
|
|
||||||
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'`
|
|
||||||
if test "$major" -gt "$req_major"; then
|
|
||||||
ok=yes
|
|
||||||
else
|
|
||||||
if test "$major" -eq "$req_major"; then
|
|
||||||
if test "$minor" -gt "$req_minor"; then
|
|
||||||
ok=yes
|
|
||||||
else
|
|
||||||
if test "$minor" -eq "$req_minor"; then
|
|
||||||
if test "$micro" -ge "$req_micro"; then
|
|
||||||
ok=yes
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if test $ok = yes; then
|
|
||||||
OPENSC_CFLAGS=`$OPENSC_CONFIG $opensc_config_args --cflags`
|
|
||||||
OPENSC_LIBS=`$OPENSC_CONFIG $opensc_config_args --libs`
|
|
||||||
OPENSC_LIBS="$OPENSC_LIBS -lpcsclite -lpthread"
|
|
||||||
AC_MSG_RESULT(yes)
|
|
||||||
ifelse([$2], , :, [$2])
|
|
||||||
else
|
|
||||||
OPENSC_CFLAGS=""
|
|
||||||
OPENSC_LIBS=""
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
ifelse([$3], , :, [$3])
|
|
||||||
fi
|
|
||||||
AC_SUBST(OPENSC_CFLAGS)
|
|
||||||
AC_SUBST(OPENSC_LIBS)
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
|||||||
# cmacros.am - C macro definitions
|
|
||||||
# Copyright (C) 2004 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
|
|
||||||
|
|
||||||
localedir = $(datadir)/locale
|
|
||||||
|
|
||||||
AM_CPPFLAGS += -DLOCALEDIR=\"$(localedir)\"
|
|
||||||
|
|
||||||
if ! HAVE_DOSISH_SYSTEM
|
|
||||||
AM_CPPFLAGS += -DGNUPG_BINDIR="\"$(bindir)\"" \
|
|
||||||
-DGNUPG_LIBEXECDIR="\"$(libexecdir)\"" \
|
|
||||||
-DGNUPG_LIBDIR="\"$(libdir)/@PACKAGE@\"" \
|
|
||||||
-DGNUPG_DATADIR="\"$(datadir)/@PACKAGE@\""
|
|
||||||
endif
|
|
||||||
|
|
||||||
if GNUPG_AGENT_PGM
|
|
||||||
AM_CPPFLAGS += -DGNUPG_DEFAULT_AGENT="\"@GNUPG_AGENT_PGM@\""
|
|
||||||
endif
|
|
||||||
if GNUPG_PINENTRY_PGM
|
|
||||||
AM_CPPFLAGS += -DGNUPG_DEFAULT_PINENTRY="\"@GNUPG_PINENTRY_PGM@\""
|
|
||||||
endif
|
|
||||||
if GNUPG_SCDAEMON_PGM
|
|
||||||
AM_CPPFLAGS += -DGNUPG_DEFAULT_SCDAEMON="\"@GNUPG_SCDAEMON_PGM@\""
|
|
||||||
endif
|
|
||||||
if GNUPG_DIRMNGR_PGM
|
|
||||||
AM_CPPFLAGS += -DGNUPG_DEFAULT_DIRMNGR="\"@GNUPG_DIRMNGR_PGM@\""
|
|
||||||
endif
|
|
||||||
if GNUPG_PROTECT_TOOL_PGM
|
|
||||||
AM_CPPFLAGS += -DGNUPG_DEFAULT_PROTECT_TOOL="\"@GNUPG_PROTECT_TOOL_PGM@\""
|
|
||||||
endif
|
|
161
autogen.sh
161
autogen.sh
@ -1,161 +0,0 @@
|
|||||||
#! /bin/sh
|
|
||||||
# Run this to generate all the initial makefiles, etc.
|
|
||||||
#
|
|
||||||
# Copyright (C) 2003 g10 Code GmbH
|
|
||||||
#
|
|
||||||
# This file is free software; as a special exception the author gives
|
|
||||||
# unlimited permission to copy and/or distribute it, with or without
|
|
||||||
# modifications, as long as this notice is preserved.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful, but
|
|
||||||
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
|
||||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
configure_ac="configure.ac"
|
|
||||||
|
|
||||||
cvtver () {
|
|
||||||
awk 'NR==1 {split($NF,A,".");X=1000000*A[1]+1000*A[2]+A[3];print X;exit 0}'
|
|
||||||
}
|
|
||||||
|
|
||||||
check_version () {
|
|
||||||
if [ `("$1" --version || echo "0") | cvtver` -ge "$2" ]; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
echo "**Error**: "\`$1\'" not installed or too old." >&2
|
|
||||||
echo ' Version '$3' or newer is required.' >&2
|
|
||||||
[ -n "$4" ] && echo ' Note that this is part of '\`$4\''.' >&2
|
|
||||||
DIE="yes"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Allow to override the default tool names
|
|
||||||
AUTOCONF=${AUTOCONF_PREFIX}${AUTOCONF:-autoconf}${AUTOCONF_SUFFIX}
|
|
||||||
AUTOHEADER=${AUTOCONF_PREFIX}${AUTOHEADER:-autoheader}${AUTOCONF_SUFFIX}
|
|
||||||
|
|
||||||
AUTOMAKE=${AUTOMAKE_PREFIX}${AUTOMAKE:-automake}${AUTOMAKE_SUFFIX}
|
|
||||||
ACLOCAL=${AUTOMAKE_PREFIX}${ACLOCAL:-aclocal}${AUTOMAKE_SUFFIX}
|
|
||||||
|
|
||||||
GETTEXT=${GETTEXT_PREFIX}${GETTEXT:-gettext}${GETTEXT_SUFFIX}
|
|
||||||
MSGMERGE=${GETTEXT_PREFIX}${MSGMERGE:-msgmerge}${GETTEXT_SUFFIX}
|
|
||||||
|
|
||||||
DIE=no
|
|
||||||
|
|
||||||
if [ "$1" = "--build-w32" ]; then
|
|
||||||
shift
|
|
||||||
target=i386--mingw32
|
|
||||||
if [ ! -f ./config.guess ]; then
|
|
||||||
echo "./config.guess not found" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
host=`./config.guess`
|
|
||||||
|
|
||||||
if ! mingw32 --version >/dev/null; then
|
|
||||||
echo "We need at least version 0.3 of MingW32/CPD" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f config.h ]; then
|
|
||||||
if grep HAVE_DOSISH_SYSTEM config.h | grep undef >/dev/null; then
|
|
||||||
echo "Pease run a 'make distclean' first" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
crossinstalldir=`mingw32 --install-dir`
|
|
||||||
crossbindir=`mingw32 --get-bindir 2>/dev/null` \
|
|
||||||
|| crossbindir="$crossinstalldir/bin"
|
|
||||||
crossdatadir=`mingw32 --get-datadir 2>/dev/null` \
|
|
||||||
|| crossdatadir="$crossinstalldir/share"
|
|
||||||
crosslibdir=`mingw32 --get-libdir 2>/dev/null` \
|
|
||||||
|| crosslibdir="$crossinstalldir/i386--mingw32/lib"
|
|
||||||
crossincdir=`mingw32 --get-includedir 2>/dev/null` \
|
|
||||||
|| crossincdir="$crossinstalldir/i386--mingw32/include"
|
|
||||||
CC=`mingw32 --get-path gcc`
|
|
||||||
CPP=`mingw32 --get-path cpp`
|
|
||||||
AR=`mingw32 --get-path ar`
|
|
||||||
RANLIB=`mingw32 --get-path ranlib`
|
|
||||||
export CC CPP AR RANLIB
|
|
||||||
|
|
||||||
disable_foo_tests=""
|
|
||||||
if [ -n "$lib_config_files" ]; then
|
|
||||||
for i in $lib_config_files; do
|
|
||||||
j=`echo $i | tr '[a-z-]' '[A-Z_]'`
|
|
||||||
eval "$j=${crossbindir}/$i"
|
|
||||||
export $j
|
|
||||||
disable_foo_tests="$disable_foo_tests --disable-`echo $i| \
|
|
||||||
sed 's,-config$,,'`-test"
|
|
||||||
if [ ! -f "${crossbindir}/$i" ]; then
|
|
||||||
echo "$i not installed for MingW32" >&2
|
|
||||||
DIE=yes
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
[ $DIE = yes ] && exit 1
|
|
||||||
|
|
||||||
./configure --host=${host} --target=${target} ${disable_foo_tests} \
|
|
||||||
--bindir=${crossbindir} --libdir=${crosslibdir} \
|
|
||||||
--datadir=${crossdatadir} --includedir=${crossincdir} \
|
|
||||||
--enable-maintainer-mode $*
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Grep the required versions from configure.ac
|
|
||||||
autoconf_vers=`sed -n '/^AC_PREREQ(/ {
|
|
||||||
s/^.*(\(.*\))/\1/p
|
|
||||||
q
|
|
||||||
}' ${configure_ac}`
|
|
||||||
autoconf_vers_num=`echo "$autoconf_vers" | cvtver`
|
|
||||||
|
|
||||||
automake_vers=`sed -n '/^min_automake_version=/ {
|
|
||||||
s/^.*="\(.*\)"/\1/p
|
|
||||||
q
|
|
||||||
}' ${configure_ac}`
|
|
||||||
automake_vers_num=`echo "$automake_vers" | cvtver`
|
|
||||||
|
|
||||||
gettext_vers=`sed -n '/^AM_GNU_GETTEXT_VERSION(/ {
|
|
||||||
s/^.*(\(.*\))/\1/p
|
|
||||||
q
|
|
||||||
}' ${configure_ac}`
|
|
||||||
gettext_vers_num=`echo "$gettext_vers" | cvtver`
|
|
||||||
|
|
||||||
|
|
||||||
if [ -z "$autoconf_vers" -o -z "$automake_vers" -o -z "$gettext_vers" ]
|
|
||||||
then
|
|
||||||
echo "**Error**: version information not found in "\`${configure_ac}\'"." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
if check_version $AUTOCONF $autoconf_vers_num $autoconf_vers ; then
|
|
||||||
check_version $AUTOHEADER $autoconf_vers_num $autoconf_vers autoconf
|
|
||||||
fi
|
|
||||||
if check_version $AUTOMAKE $automake_vers_num $automake_vers; then
|
|
||||||
check_version $ACLOCAL $automake_vers_num $autoconf_vers automake
|
|
||||||
fi
|
|
||||||
if check_version $GETTEXT $gettext_vers_num $gettext_vers; then
|
|
||||||
check_version $MSGMERGE $gettext_vers_num $gettext_vers gettext
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$DIE" = "yes"; then
|
|
||||||
cat <<EOF
|
|
||||||
|
|
||||||
Note that you may use alternative versions of the tools by setting
|
|
||||||
the corresponding environment variables; see README.CVS for details.
|
|
||||||
|
|
||||||
EOF
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
echo "Running aclocal -I m4 ${ACLOCAL_FLAGS:+$ACLOCAL_FLAGS }..."
|
|
||||||
$ACLOCAL -I m4 $ACLOCAL_FLAGS
|
|
||||||
echo "Running autoheader..."
|
|
||||||
$AUTOHEADER
|
|
||||||
echo "Running automake --gnu ..."
|
|
||||||
$AUTOMAKE --gnu;
|
|
||||||
echo "Running autoconf..."
|
|
||||||
$AUTOCONF
|
|
||||||
|
|
||||||
echo "You may now run \"./configure --enable-maintainer-mode && make\"."
|
|
340
common/ChangeLog
340
common/ChangeLog
@ -1,340 +0,0 @@
|
|||||||
2004-06-14 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* xreadline.c: New. Based on the iobuf_read_line function.
|
|
||||||
|
|
||||||
2004-05-12 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* util.h (xtrycalloc_secure,xtrymalloc_secure): New.
|
|
||||||
|
|
||||||
2004-05-11 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* sysutils.c (disable_core_dumps): Only set the current limit.
|
|
||||||
(enable_core_dumps): New.
|
|
||||||
|
|
||||||
2004-04-13 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* simple-pwquery.c (copy_and_escape): Relaxed quoting.
|
|
||||||
|
|
||||||
2004-04-05 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* errors.h (STATUS_NEWSIG): New.
|
|
||||||
|
|
||||||
2004-03-11 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* dynload.h [__MINGW32__]: Define RTLD_LAZY.
|
|
||||||
|
|
||||||
2004-03-09 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* maperror.c (map_assuan_err): Map the Locale_Problem item.
|
|
||||||
|
|
||||||
2004-03-03 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* asshelp.c, asshelp.h: New.
|
|
||||||
(send_pinentry_environment): New. Code taken from ../sm/call-agent.c.
|
|
||||||
|
|
||||||
2004-02-19 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* simple-pwquery.c (agent_open): Don't mangle INFOSTR.
|
|
||||||
|
|
||||||
2004-02-17 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* simple-pwquery.c (agent_open): Ignore an empty GPG_AGENT_INFO.
|
|
||||||
|
|
||||||
* errors.h: Added STATUS_IMPORT_OK.
|
|
||||||
|
|
||||||
2004-02-10 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* b64enc.c: New. Based on code from ../sm/base64.c.
|
|
||||||
|
|
||||||
2004-01-30 Marcus Brinkmann <marcus@g10code.de>
|
|
||||||
|
|
||||||
* Makefile.am (libcommon_a_SOURCES): Add xasprintf.c.
|
|
||||||
* miscellaneous.c (xasprintf): Moved to ...
|
|
||||||
* xasprintf (xasprintf): ... here. New file.
|
|
||||||
This allows to use xasprintf without sucking in gpg-error.
|
|
||||||
|
|
||||||
2004-01-27 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* sexp-parse.h: New; moved from../agent.
|
|
||||||
|
|
||||||
* util.h (xtoi_4): New.
|
|
||||||
|
|
||||||
2003-12-23 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* maperror.c (map_assuan_err): Prepared for a new error code.
|
|
||||||
|
|
||||||
2003-12-17 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gettime.c (asctimestamp): Add a note on a non-avoidable gcc warning.
|
|
||||||
|
|
||||||
* util.h [!HAVE_VASPRINTF]: Add printf format attribute to the
|
|
||||||
replacement function.
|
|
||||||
|
|
||||||
* miscellaneous.c (xasprintf): New.
|
|
||||||
|
|
||||||
2003-11-14 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* mkdtemp.c (mkdtemp): Use gcry_create_nonce.
|
|
||||||
|
|
||||||
* cryptmiss.c: Removed.
|
|
||||||
|
|
||||||
2003-11-13 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* util.h (vasprintf): Also fixed the prototype.
|
|
||||||
|
|
||||||
* vasprintf.c (vasprintf): ARGS should not be a pointer. Fixed
|
|
||||||
segv on Solaris. Reported by Andrew J. Schorr.
|
|
||||||
|
|
||||||
2003-11-12 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* maperror.c (map_ksba_err, map_gcry_err, map_kbx_err): Removed.
|
|
||||||
|
|
||||||
2003-10-31 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* util.h (gnupg_isotime_t): New.
|
|
||||||
(gnupg_copy_time): New.
|
|
||||||
|
|
||||||
* gettime.c (gnupg_get_isotime): New.
|
|
||||||
|
|
||||||
2003-09-23 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* iobuf.c (check_special_filename): Replaced is isdigit by digitp
|
|
||||||
to avoid passing negative values and potential locale problems.
|
|
||||||
Problem noted by Christian Biere.
|
|
||||||
|
|
||||||
* util.h (ascii_isspace): New.
|
|
||||||
|
|
||||||
2003-09-18 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* ttyio.c (tty_fprintf): New.
|
|
||||||
(tty_print_string, tty_print_utf8_string2)
|
|
||||||
(tty_print_utf8_string): Made P argument const byte*.
|
|
||||||
|
|
||||||
2003-08-20 Marcus Brinkmann <marcus@g10code.de>
|
|
||||||
|
|
||||||
* maperror.c (map_ksba_err): Map -1. Use gpg_err_make to set
|
|
||||||
the error source.
|
|
||||||
|
|
||||||
2003-08-14 Timo Schulz <twoaday@freakmail.de>
|
|
||||||
|
|
||||||
* dynload.h. New. W32 wrapper around the dynload mechanism.
|
|
||||||
|
|
||||||
2003-07-15 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* simple-pwquery.c, simple-pwquery.h: New; moved from ../agent.
|
|
||||||
* Makefile.am (libsimple_pwquery_a_LIBADD): New.
|
|
||||||
|
|
||||||
2003-06-25 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* maperror.c (map_to_assuan_status): Directly map 0 to 0.
|
|
||||||
|
|
||||||
2003-06-17 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gettime.c (scan_isodatestr,add_days_to_timestamp,strtimevalue)
|
|
||||||
(strtimestamp,asctimestamp): New. Code taken from gnupg 1.3.2
|
|
||||||
mischelp.c.
|
|
||||||
|
|
||||||
* yesno.c: New. Code taken from gnupg 1.3.2 mischelp.c
|
|
||||||
|
|
||||||
* miscellaneous.c: New.
|
|
||||||
|
|
||||||
* util.h: Include utf8conf.h
|
|
||||||
|
|
||||||
2003-06-16 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gettime.c (make_timestamp): New.
|
|
||||||
|
|
||||||
* ttyio.c: New. Taken from gnupg 1.2.
|
|
||||||
* ttyio.h: Move from ../include.
|
|
||||||
|
|
||||||
2003-06-13 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* util.h (seterr): Removed macro.
|
|
||||||
(xmalloc_secure,xcalloc_secure): New.
|
|
||||||
|
|
||||||
2003-06-11 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* iobuf.c (iobuf_writebyte,iobuf_write): Return error code from
|
|
||||||
iobuf_flush.
|
|
||||||
(iobuf_writestr): Ditto.
|
|
||||||
|
|
||||||
2003-06-10 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* iobuf.c, iobuf.h: New. Taken from current gnupg 1.3 CVS. Run
|
|
||||||
indent on it and adjusted error handling to libgpg-error style.
|
|
||||||
Replaced IOBUF by iobuf_t. Renamed malloc functions.
|
|
||||||
|
|
||||||
2003-06-04 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* errors.h: Removed all error codes. We keep the status codes for
|
|
||||||
now.
|
|
||||||
* Makefile.am: Do not create errors.c anymore; remove it from the
|
|
||||||
sources.
|
|
||||||
|
|
||||||
* maperror.c: Don't include error.h. Change all error codes to
|
|
||||||
libgpg-error style.
|
|
||||||
(map_assuan_err): Changed to new Assuan error code convention.
|
|
||||||
(map_to_assuan_status): Likewise.
|
|
||||||
(map_gcry_err,map_kbx_err): Not needed. For now dummy functions.
|
|
||||||
|
|
||||||
* membuf.c, membuf.h: New. Code taken from ../sm/call-agent.h.
|
|
||||||
* Makefile.am: Added above.
|
|
||||||
|
|
||||||
2003-04-29 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* util.h (fopencokokie): Removed prototype and struct.
|
|
||||||
|
|
||||||
* fopencookie.c: Removed.
|
|
||||||
|
|
||||||
* maperror.c: Use system assuan.h
|
|
||||||
|
|
||||||
2002-10-31 Neal H. Walfield <neal@g10code.de>
|
|
||||||
|
|
||||||
* isascii.c: New file.
|
|
||||||
* putc_unlocked.c: Likewise.
|
|
||||||
|
|
||||||
2002-10-28 Neal H. Walfield <neal@g10code.de>
|
|
||||||
|
|
||||||
* signal.c (caught_fatal_sig): Remove superfluous zero
|
|
||||||
initializer.
|
|
||||||
(caught_sigusr1): Likewise.
|
|
||||||
|
|
||||||
2002-09-04 Neal H. Walfield <neal@g10code.de>
|
|
||||||
|
|
||||||
* vasprintf.c (vasprintf) [va_copy]: Use va_copy.
|
|
||||||
[!va_copy && __va_copy]: Use __va_copy.
|
|
||||||
[!va_copy && !__va_copy]: Only now fall back to using memcpy.
|
|
||||||
|
|
||||||
2002-08-21 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* errors.h: Added STATUS_IMPORT_PROBLEM.
|
|
||||||
|
|
||||||
2002-08-20 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* vasprintf.c: Hack to handle NULL for %s.
|
|
||||||
|
|
||||||
2002-08-09 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* signal.c: New. Taken from GnuPG 1.1.91.
|
|
||||||
|
|
||||||
2002-07-23 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* util.h (_IO_cookie_io_functions_t): Fixed typo. Noted by
|
|
||||||
Richard Lefebvre.
|
|
||||||
|
|
||||||
2002-07-22 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* fseeko.c, ftello.c: New.
|
|
||||||
|
|
||||||
2002-06-28 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* maperror.c (map_to_assuan_status): Map more errorcodes to Bad
|
|
||||||
Certificate.
|
|
||||||
|
|
||||||
2002-06-26 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* maperror.c (map_to_assuan_status): Map EOF to No_Data_Available.
|
|
||||||
|
|
||||||
2002-06-10 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* errors.h (gnupg_error_token): Add new prototype.
|
|
||||||
(STATUS_ERROR): New.
|
|
||||||
|
|
||||||
* mkerrtok: New.
|
|
||||||
* Makefile.am: Use it to create the new error token function.
|
|
||||||
|
|
||||||
2002-06-04 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* maperror.c (map_to_assuan_status): Map Bad_CA_Certificate.
|
|
||||||
|
|
||||||
2002-05-23 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* no-pth.c, Makefile.am: Removed.
|
|
||||||
|
|
||||||
2002-05-22 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* mkdtemp.c: Replaced byte by unsigned char because it is no longer
|
|
||||||
defined in gcrypt.h.
|
|
||||||
|
|
||||||
2002-05-21 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* maperror.c (map_gcry_err): Add libgcrypt's new S-expression errors.
|
|
||||||
(map_ksba_err): Add a few mappings.
|
|
||||||
|
|
||||||
2002-05-14 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gettime.c: New.
|
|
||||||
|
|
||||||
2002-05-03 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* errors.h: Added STARUS_EXPSIG and STATUS_EXPKEYSIG.
|
|
||||||
|
|
||||||
2002-04-15 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* cryptmiss.c: New.
|
|
||||||
|
|
||||||
2002-02-14 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* maperror.c: Add more assuan<->gnupg mappings.
|
|
||||||
|
|
||||||
2002-02-12 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* fopencookie.c: Dummy function.
|
|
||||||
|
|
||||||
* vasprintf.c: New. Taken from binutils-2.9.1 and dropped all non
|
|
||||||
ANSI-C stuff. Merged with asprintf version.
|
|
||||||
|
|
||||||
* no-pth.c: New.
|
|
||||||
|
|
||||||
2002-01-23 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* mkdtemp.c: Copied from gnupg-1.0.6c and changed to use libgcrypt.
|
|
||||||
|
|
||||||
2002-01-19 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* sysutils.c: New. This is the misc.c file from gnupg 1.0.6 with
|
|
||||||
the OpenPGP stuff removed.
|
|
||||||
* sysutils.h: New.
|
|
||||||
|
|
||||||
2002-01-15 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* maperror.c: Add mapping for Not_Trusted.
|
|
||||||
|
|
||||||
2002-01-11 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* maperror.c (map_assuan_err): Codes for CRL
|
|
||||||
|
|
||||||
2002-01-08 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* util.h (spacep): New.
|
|
||||||
|
|
||||||
2002-01-02 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* maperror.c (map_to_assuan_status): New. Merged from ../agent
|
|
||||||
and ../sm.
|
|
||||||
|
|
||||||
2001-12-20 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* maperror.c (map_gcry_err): Add some mappings.
|
|
||||||
|
|
||||||
2001-12-18 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* Makefile.am (AM_CPPFLAGS): Include flags for gcrypt and ksba
|
|
||||||
|
|
||||||
2001-12-14 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* util.h (digitp, hexdigitp): New ctype like macros.
|
|
||||||
(atoi_1,atoi_2,atoi_4,xtoi_1,xtoi_2): New.
|
|
||||||
|
|
||||||
|
|
||||||
Copyright 2001, 2002 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is free software; as a special exception the author gives
|
|
||||||
unlimited permission to copy and/or distribute it, with or without
|
|
||||||
modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
This file is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
|
||||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
|||||||
# Makefile for common gnupg modules
|
|
||||||
# Copyright (C) 2001, 2003 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
|
|
||||||
|
|
||||||
## Process this file with automake to produce Makefile.in
|
|
||||||
|
|
||||||
EXTRA_DIST = mkerrors mkerrtok
|
|
||||||
|
|
||||||
noinst_LIBRARIES = libcommon.a libsimple-pwquery.a
|
|
||||||
|
|
||||||
AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS)
|
|
||||||
|
|
||||||
libcommon_a_SOURCES = \
|
|
||||||
util.h i18n.h \
|
|
||||||
errors.h \
|
|
||||||
sexp-parse.h \
|
|
||||||
maperror.c \
|
|
||||||
sysutils.c sysutils.h \
|
|
||||||
gettime.c \
|
|
||||||
yesno.c \
|
|
||||||
b64enc.c \
|
|
||||||
miscellaneous.c \
|
|
||||||
xasprintf.c \
|
|
||||||
xreadline.c \
|
|
||||||
membuf.c membuf.h \
|
|
||||||
iobuf.c iobuf.h \
|
|
||||||
ttyio.c ttyio.h \
|
|
||||||
asshelp.c asshelp.h \
|
|
||||||
signal.c \
|
|
||||||
dynload.h
|
|
||||||
|
|
||||||
|
|
||||||
libcommon_a_LIBADD = @LIBOBJS@
|
|
||||||
|
|
||||||
libsimple_pwquery_a_SOURCES = \
|
|
||||||
simple-pwquery.c simple-pwquery.h asshelp.c asshelp.h
|
|
||||||
|
|
||||||
libsimple_pwquery_a_LIBADD = @LIBOBJS@
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
|||||||
Stuff used by several modules of GnuPG.
|
|
||||||
|
|
||||||
These directories use it:
|
|
||||||
|
|
||||||
gpg
|
|
||||||
sm
|
|
||||||
agent
|
|
||||||
|
|
||||||
These directories don't use it:
|
|
||||||
|
|
||||||
kbx
|
|
166
common/asshelp.c
166
common/asshelp.c
@ -1,166 +0,0 @@
|
|||||||
/* asshelp.c - Helper functions for Assuan
|
|
||||||
* Copyright (C) 2002, 2004 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#ifdef HAVE_LOCALE_H
|
|
||||||
#include <locale.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
#include "asshelp.h"
|
|
||||||
|
|
||||||
/* Send the assuan command pertaining to the pinenry environment. The
|
|
||||||
OPT_* arguments are optional and may be used to overide the
|
|
||||||
defaults taken from the current locale. */
|
|
||||||
gpg_error_t
|
|
||||||
send_pinentry_environment (assuan_context_t ctx,
|
|
||||||
const char *opt_display,
|
|
||||||
const char *opt_ttyname,
|
|
||||||
const char *opt_ttytype,
|
|
||||||
const char *opt_lc_ctype,
|
|
||||||
const char *opt_lc_messages)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
char *dft_display = NULL;
|
|
||||||
char *dft_ttyname = NULL;
|
|
||||||
char *dft_ttytype = NULL;
|
|
||||||
char *old_lc = NULL;
|
|
||||||
char *dft_lc = NULL;
|
|
||||||
|
|
||||||
dft_display = getenv ("DISPLAY");
|
|
||||||
if (opt_display || dft_display)
|
|
||||||
{
|
|
||||||
char *optstr;
|
|
||||||
if (asprintf (&optstr, "OPTION display=%s",
|
|
||||||
opt_display ? opt_display : dft_display) < 0)
|
|
||||||
return gpg_error_from_errno (errno);
|
|
||||||
rc = assuan_transact (ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
NULL);
|
|
||||||
free (optstr);
|
|
||||||
if (rc)
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
if (!opt_ttyname)
|
|
||||||
{
|
|
||||||
dft_ttyname = getenv ("GPG_TTY");
|
|
||||||
if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
|
|
||||||
dft_ttyname = ttyname (0);
|
|
||||||
}
|
|
||||||
if (opt_ttyname || dft_ttyname)
|
|
||||||
{
|
|
||||||
char *optstr;
|
|
||||||
if (asprintf (&optstr, "OPTION ttyname=%s",
|
|
||||||
opt_ttyname ? opt_ttyname : dft_ttyname) < 0)
|
|
||||||
return gpg_error_from_errno (errno);
|
|
||||||
rc = assuan_transact (ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
NULL);
|
|
||||||
free (optstr);
|
|
||||||
if (rc)
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
dft_ttytype = getenv ("TERM");
|
|
||||||
if (opt_ttytype || (dft_ttyname && dft_ttytype))
|
|
||||||
{
|
|
||||||
char *optstr;
|
|
||||||
if (asprintf (&optstr, "OPTION ttytype=%s",
|
|
||||||
opt_ttyname ? opt_ttytype : dft_ttytype) < 0)
|
|
||||||
return gpg_error_from_errno (errno);
|
|
||||||
rc = assuan_transact (ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
NULL);
|
|
||||||
free (optstr);
|
|
||||||
if (rc)
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
|
|
||||||
old_lc = setlocale (LC_CTYPE, NULL);
|
|
||||||
if (old_lc)
|
|
||||||
{
|
|
||||||
old_lc = strdup (old_lc);
|
|
||||||
if (!old_lc)
|
|
||||||
return gpg_error_from_errno (errno);
|
|
||||||
}
|
|
||||||
dft_lc = setlocale (LC_CTYPE, "");
|
|
||||||
#endif
|
|
||||||
if (opt_lc_ctype || (dft_ttyname && dft_lc))
|
|
||||||
{
|
|
||||||
char *optstr;
|
|
||||||
if (asprintf (&optstr, "OPTION lc-ctype=%s",
|
|
||||||
opt_lc_ctype ? opt_lc_ctype : dft_lc) < 0)
|
|
||||||
rc = gpg_error_from_errno (errno);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rc = assuan_transact (ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
NULL);
|
|
||||||
free (optstr);
|
|
||||||
if (rc)
|
|
||||||
rc = map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
|
|
||||||
if (old_lc)
|
|
||||||
{
|
|
||||||
setlocale (LC_CTYPE, old_lc);
|
|
||||||
free (old_lc);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
|
|
||||||
old_lc = setlocale (LC_MESSAGES, NULL);
|
|
||||||
if (old_lc)
|
|
||||||
{
|
|
||||||
old_lc = strdup (old_lc);
|
|
||||||
if (!old_lc)
|
|
||||||
return gpg_error_from_errno (errno);
|
|
||||||
}
|
|
||||||
dft_lc = setlocale (LC_MESSAGES, "");
|
|
||||||
#endif
|
|
||||||
if (opt_lc_messages || (dft_ttyname && dft_lc))
|
|
||||||
{
|
|
||||||
char *optstr;
|
|
||||||
if (asprintf (&optstr, "OPTION lc-messages=%s",
|
|
||||||
opt_lc_messages ? opt_lc_messages : dft_lc) < 0)
|
|
||||||
rc = gpg_error_from_errno (errno);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rc = assuan_transact (ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
NULL);
|
|
||||||
free (optstr);
|
|
||||||
if (rc)
|
|
||||||
rc = map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
|
|
||||||
if (old_lc)
|
|
||||||
{
|
|
||||||
setlocale (LC_MESSAGES, old_lc);
|
|
||||||
free (old_lc);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
/* asshelp.h - Helper functions for Assuan
|
|
||||||
* Copyright (C) 2004 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 GNUPG_COMMON_ASSHELP_H
|
|
||||||
#define GNUPG_COMMON_ASSHELP_H
|
|
||||||
|
|
||||||
#include <assuan.h>
|
|
||||||
#include <gpg-error.h>
|
|
||||||
|
|
||||||
gpg_error_t
|
|
||||||
send_pinentry_environment (assuan_context_t ctx,
|
|
||||||
const char *opt_display,
|
|
||||||
const char *opt_ttyname,
|
|
||||||
const char *opt_ttytype,
|
|
||||||
const char *opt_lc_ctype,
|
|
||||||
const char *opt_lc_messages);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*GNUPG_COMMON_ASSHELP_H*/
|
|
211
common/b64enc.c
211
common/b64enc.c
@ -1,211 +0,0 @@
|
|||||||
/* b64enc.c - Simple Base64 encoder.
|
|
||||||
* Copyright (C) 2001, 2003, 2004 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "i18n.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
#define B64ENC_DID_HEADER 1
|
|
||||||
#define B64ENC_DID_TRAILER 2
|
|
||||||
#define B64ENC_NO_LINEFEEDS 16
|
|
||||||
|
|
||||||
|
|
||||||
/* The base-64 character list */
|
|
||||||
static unsigned char bintoasc[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
||||||
"abcdefghijklmnopqrstuvwxyz"
|
|
||||||
"0123456789+/";
|
|
||||||
|
|
||||||
/* Prepare for base-64 writing to the stream FP. If TITLE is not NULL
|
|
||||||
and not an empty string, this string will be used as the title for
|
|
||||||
the armor lines, with TITLE being an empty string, we don't write
|
|
||||||
the header lines and furthermore even don't write any linefeeds.
|
|
||||||
With TITLE beeing NULL, we merely don't write header but make sure
|
|
||||||
that lines are not too long. Note, that we don't write any output
|
|
||||||
unless at least one byte get written using b64enc_write. */
|
|
||||||
gpg_error_t
|
|
||||||
b64enc_start (struct b64state *state, FILE *fp, const char *title)
|
|
||||||
{
|
|
||||||
memset (state, 0, sizeof *state);
|
|
||||||
state->fp = fp;
|
|
||||||
if (title && !*title)
|
|
||||||
state->flags |= B64ENC_NO_LINEFEEDS;
|
|
||||||
else if (title)
|
|
||||||
{
|
|
||||||
state->title = xtrystrdup (title);
|
|
||||||
if (!state->title)
|
|
||||||
return gpg_error_from_errno (errno);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Write NBYTES from BUFFER to the Base 64 stream identified by
|
|
||||||
STATE. With BUFFER and NBYTES being 0, merely do a fflush on the
|
|
||||||
stream. */
|
|
||||||
gpg_error_t
|
|
||||||
b64enc_write (struct b64state *state, const void *buffer, size_t nbytes)
|
|
||||||
{
|
|
||||||
unsigned char radbuf[4];
|
|
||||||
int idx, quad_count;
|
|
||||||
const unsigned char *p;
|
|
||||||
FILE *fp = state->fp;
|
|
||||||
|
|
||||||
|
|
||||||
if (!nbytes)
|
|
||||||
{
|
|
||||||
if (buffer && fflush (fp))
|
|
||||||
goto write_error;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(state->flags & B64ENC_DID_HEADER))
|
|
||||||
{
|
|
||||||
if (state->title)
|
|
||||||
{
|
|
||||||
if ( fputs ("-----BEGIN ", fp) == EOF
|
|
||||||
|| fputs (state->title, fp) == EOF
|
|
||||||
|| fputs ("-----\n", fp) == EOF)
|
|
||||||
goto write_error;
|
|
||||||
}
|
|
||||||
state->flags |= B64ENC_DID_HEADER;
|
|
||||||
}
|
|
||||||
|
|
||||||
idx = state->idx;
|
|
||||||
quad_count = state->quad_count;
|
|
||||||
assert (idx < 4);
|
|
||||||
memcpy (radbuf, state->radbuf, idx);
|
|
||||||
|
|
||||||
for (p=buffer; nbytes; p++, nbytes--)
|
|
||||||
{
|
|
||||||
radbuf[idx++] = *p;
|
|
||||||
if (idx > 2)
|
|
||||||
{
|
|
||||||
char tmp[4];
|
|
||||||
|
|
||||||
tmp[0] = bintoasc[(*radbuf >> 2) & 077];
|
|
||||||
tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
|
|
||||||
tmp[2] = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
|
|
||||||
tmp[3] = bintoasc[radbuf[2]&077];
|
|
||||||
for (idx=0; idx < 4; idx++)
|
|
||||||
putc (tmp[idx], fp);
|
|
||||||
idx = 0;
|
|
||||||
if (ferror (fp))
|
|
||||||
goto write_error;
|
|
||||||
if (++quad_count >= (64/4))
|
|
||||||
{
|
|
||||||
quad_count = 0;
|
|
||||||
if (!(state->flags & B64ENC_NO_LINEFEEDS)
|
|
||||||
&& fputs ("\n", fp) == EOF)
|
|
||||||
goto write_error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memcpy (state->radbuf, radbuf, idx);
|
|
||||||
state->idx = idx;
|
|
||||||
state->quad_count = quad_count;
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
write_error:
|
|
||||||
return gpg_error_from_errno (errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
gpg_error_t
|
|
||||||
b64enc_finish (struct b64state *state)
|
|
||||||
{
|
|
||||||
gpg_error_t err = 0;
|
|
||||||
unsigned char radbuf[4];
|
|
||||||
int idx, quad_count;
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
if (!(state->flags & B64ENC_DID_HEADER))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/* Flush the base64 encoding */
|
|
||||||
fp = state->fp;
|
|
||||||
idx = state->idx;
|
|
||||||
quad_count = state->quad_count;
|
|
||||||
assert (idx < 4);
|
|
||||||
memcpy (radbuf, state->radbuf, idx);
|
|
||||||
|
|
||||||
if (idx)
|
|
||||||
{
|
|
||||||
char tmp[4];
|
|
||||||
|
|
||||||
tmp[0] = bintoasc[(*radbuf>>2)&077];
|
|
||||||
if (idx == 1)
|
|
||||||
{
|
|
||||||
tmp[1] = bintoasc[((*radbuf << 4) & 060) & 077];
|
|
||||||
tmp[2] = '=';
|
|
||||||
tmp[3] = '=';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
|
|
||||||
tmp[2] = bintoasc[((radbuf[1] << 2) & 074) & 077];
|
|
||||||
tmp[3] = '=';
|
|
||||||
}
|
|
||||||
for (idx=0; idx < 4; idx++)
|
|
||||||
putc (tmp[idx], fp);
|
|
||||||
idx = 0;
|
|
||||||
if (ferror (fp))
|
|
||||||
goto write_error;
|
|
||||||
|
|
||||||
if (++quad_count >= (64/4))
|
|
||||||
{
|
|
||||||
quad_count = 0;
|
|
||||||
if (!(state->flags & B64ENC_NO_LINEFEEDS)
|
|
||||||
&& fputs ("\n", fp) == EOF)
|
|
||||||
goto write_error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finish the last line and write the trailer. */
|
|
||||||
if (quad_count
|
|
||||||
&& !(state->flags & B64ENC_NO_LINEFEEDS)
|
|
||||||
&& fputs ("\n", fp) == EOF)
|
|
||||||
goto write_error;
|
|
||||||
|
|
||||||
if (state->title)
|
|
||||||
{
|
|
||||||
if ( fputs ("-----END ", fp) == EOF
|
|
||||||
|| fputs (state->title, fp) == EOF
|
|
||||||
|| fputs ("-----\n", fp) == EOF)
|
|
||||||
goto write_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
write_error:
|
|
||||||
err = gpg_error_from_errno (errno);
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
if (state->title)
|
|
||||||
{
|
|
||||||
xfree (state->title);
|
|
||||||
state->title = NULL;
|
|
||||||
}
|
|
||||||
state->fp = NULL;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
|||||||
/* dlfcn.h - W32 functions for run-time dynamic loading
|
|
||||||
* Copyright (C) 2003 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 GNUPG_DYNLOAD_H
|
|
||||||
#define GNUPG_DYNLOAD_H
|
|
||||||
#ifndef __MINGW32__
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#else
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#define RTLD_LAZY 0
|
|
||||||
|
|
||||||
static __inline__ void *
|
|
||||||
dlopen (const char * name, int flag)
|
|
||||||
{
|
|
||||||
void * hd = LoadLibrary (name);
|
|
||||||
return hd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ void *
|
|
||||||
dlsym (void *hd, const char *sym)
|
|
||||||
{
|
|
||||||
if (hd && sym)
|
|
||||||
{
|
|
||||||
void * fnc = GetProcAddress (hd, sym);
|
|
||||||
if (!fnc)
|
|
||||||
return NULL;
|
|
||||||
return fnc;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static __inline__ const char *
|
|
||||||
dlerror (void)
|
|
||||||
{
|
|
||||||
static char buf[32];
|
|
||||||
sprintf (buf, "ec=%lu", GetLastError ());
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static __inline__ int
|
|
||||||
dlclose (void * hd)
|
|
||||||
{
|
|
||||||
if (hd)
|
|
||||||
{
|
|
||||||
CloseHandle (hd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif /*__MINGW32__*/
|
|
||||||
#endif /*GNUPG_DYNLOAD_H*/
|
|
112
common/errors.h
112
common/errors.h
@ -1,112 +0,0 @@
|
|||||||
/* errors.h - Globally used error codes
|
|
||||||
* Copyright (C) 2001 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 GNUPG_COMMON_ERRORS_H
|
|
||||||
#define GNUPG_COMMON_ERRORS_H
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
/* Status codes - fixme: should go into another file */
|
|
||||||
enum {
|
|
||||||
STATUS_ENTER,
|
|
||||||
STATUS_LEAVE,
|
|
||||||
STATUS_ABORT,
|
|
||||||
STATUS_GOODSIG,
|
|
||||||
STATUS_BADSIG,
|
|
||||||
STATUS_ERRSIG,
|
|
||||||
STATUS_BADARMOR,
|
|
||||||
STATUS_RSA_OR_IDEA,
|
|
||||||
STATUS_SIGEXPIRED,
|
|
||||||
STATUS_KEYREVOKED,
|
|
||||||
STATUS_TRUST_UNDEFINED,
|
|
||||||
STATUS_TRUST_NEVER,
|
|
||||||
STATUS_TRUST_MARGINAL,
|
|
||||||
STATUS_TRUST_FULLY,
|
|
||||||
STATUS_TRUST_ULTIMATE,
|
|
||||||
|
|
||||||
STATUS_SHM_INFO,
|
|
||||||
STATUS_SHM_GET,
|
|
||||||
STATUS_SHM_GET_BOOL,
|
|
||||||
STATUS_SHM_GET_HIDDEN,
|
|
||||||
|
|
||||||
STATUS_NEED_PASSPHRASE,
|
|
||||||
STATUS_VALIDSIG,
|
|
||||||
STATUS_SIG_ID,
|
|
||||||
STATUS_ENC_TO,
|
|
||||||
STATUS_NODATA,
|
|
||||||
STATUS_BAD_PASSPHRASE,
|
|
||||||
STATUS_NO_PUBKEY,
|
|
||||||
STATUS_NO_SECKEY,
|
|
||||||
STATUS_NEED_PASSPHRASE_SYM,
|
|
||||||
STATUS_DECRYPTION_FAILED,
|
|
||||||
STATUS_DECRYPTION_OKAY,
|
|
||||||
STATUS_MISSING_PASSPHRASE,
|
|
||||||
STATUS_GOOD_PASSPHRASE,
|
|
||||||
STATUS_GOODMDC,
|
|
||||||
STATUS_BADMDC,
|
|
||||||
STATUS_ERRMDC,
|
|
||||||
STATUS_IMPORTED,
|
|
||||||
STATUS_IMPORT_OK,
|
|
||||||
STATUS_IMPORT_PROBLEM,
|
|
||||||
STATUS_IMPORT_RES,
|
|
||||||
STATUS_FILE_START,
|
|
||||||
STATUS_FILE_DONE,
|
|
||||||
STATUS_FILE_ERROR,
|
|
||||||
|
|
||||||
STATUS_BEGIN_DECRYPTION,
|
|
||||||
STATUS_END_DECRYPTION,
|
|
||||||
STATUS_BEGIN_ENCRYPTION,
|
|
||||||
STATUS_END_ENCRYPTION,
|
|
||||||
|
|
||||||
STATUS_DELETE_PROBLEM,
|
|
||||||
STATUS_GET_BOOL,
|
|
||||||
STATUS_GET_LINE,
|
|
||||||
STATUS_GET_HIDDEN,
|
|
||||||
STATUS_GOT_IT,
|
|
||||||
STATUS_PROGRESS,
|
|
||||||
STATUS_SIG_CREATED,
|
|
||||||
STATUS_SESSION_KEY,
|
|
||||||
STATUS_NOTATION_NAME,
|
|
||||||
STATUS_NOTATION_DATA,
|
|
||||||
STATUS_POLICY_URL,
|
|
||||||
STATUS_BEGIN_STREAM,
|
|
||||||
STATUS_END_STREAM,
|
|
||||||
STATUS_KEY_CREATED,
|
|
||||||
STATUS_USERID_HIN,
|
|
||||||
STATUS_UNEXPECTED,
|
|
||||||
STATUS_INV_RECP,
|
|
||||||
STATUS_NO_RECP,
|
|
||||||
STATUS_ALREADY_SIGNED,
|
|
||||||
|
|
||||||
STATUS_EXPSIG,
|
|
||||||
STATUS_EXPKEYSIG,
|
|
||||||
|
|
||||||
STATUS_TRUNCATED,
|
|
||||||
STATUS_ERROR,
|
|
||||||
STATUS_NEWSIG
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*-- errors.c (build by mkerror and mkerrtok) --*/
|
|
||||||
const char *gnupg_strerror (int err);
|
|
||||||
const char *gnupg_error_token (int err);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*GNUPG_COMMON_ERRORS_H*/
|
|
@ -1,40 +0,0 @@
|
|||||||
/* fseeko.c - libc replacement function
|
|
||||||
* Copyright (C) 2001 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int
|
|
||||||
fseeko (FILE *stream, off_t off, int whence)
|
|
||||||
{
|
|
||||||
return fseek (stream, off, whence);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
|||||||
/* ftello.c - libc replacement function
|
|
||||||
* Copyright (C) 2001 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
off_t
|
|
||||||
ftello (FILE *stream)
|
|
||||||
{
|
|
||||||
long int off;
|
|
||||||
|
|
||||||
off = ftell (stream);
|
|
||||||
if (off == -1)
|
|
||||||
return (off_t)-1;
|
|
||||||
return off;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
278
common/gettime.c
278
common/gettime.c
@ -1,278 +0,0 @@
|
|||||||
/* gettime.c - Wrapper for time functions
|
|
||||||
* Copyright (C) 1998, 2002 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <time.h>
|
|
||||||
#ifdef HAVE_LANGINFO_H
|
|
||||||
#include <langinfo.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
static unsigned long timewarp;
|
|
||||||
static enum { NORMAL = 0, FROZEN, FUTURE, PAST } timemode;
|
|
||||||
|
|
||||||
/* Wrapper for the time(3). We use this here so we can fake the time
|
|
||||||
for tests */
|
|
||||||
time_t
|
|
||||||
gnupg_get_time ()
|
|
||||||
{
|
|
||||||
time_t current = time (NULL);
|
|
||||||
if (timemode == NORMAL)
|
|
||||||
return current;
|
|
||||||
else if (timemode == FROZEN)
|
|
||||||
return timewarp;
|
|
||||||
else if (timemode == FUTURE)
|
|
||||||
return current + timewarp;
|
|
||||||
else
|
|
||||||
return current - timewarp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Return the current time (possibly faked) in ISO format. */
|
|
||||||
void
|
|
||||||
gnupg_get_isotime (gnupg_isotime_t timebuf)
|
|
||||||
{
|
|
||||||
time_t atime = gnupg_get_time ();
|
|
||||||
|
|
||||||
if (atime < 0)
|
|
||||||
*timebuf = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
struct tm *tp;
|
|
||||||
#ifdef HAVE_GMTIME_R
|
|
||||||
struct tm tmbuf;
|
|
||||||
|
|
||||||
tp = gmtime_r (&atime, &tmbuf);
|
|
||||||
#else
|
|
||||||
tp = gmtime (&atime);
|
|
||||||
#endif
|
|
||||||
sprintf (timebuf,"%04d%02d%02dT%02d%02d%02d",
|
|
||||||
1900 + tp->tm_year, tp->tm_mon+1, tp->tm_mday,
|
|
||||||
tp->tm_hour, tp->tm_min, tp->tm_sec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* set the time to NEWTIME so that gnupg_get_time returns a time
|
|
||||||
starting with this one. With FREEZE set to 1 the returned time
|
|
||||||
will never change. Just for completeness, a value of (time_t)-1
|
|
||||||
for NEWTIME gets you back to rality. Note that this is obviously
|
|
||||||
not thread-safe but this is not required. */
|
|
||||||
void
|
|
||||||
gnupg_set_time (time_t newtime, int freeze)
|
|
||||||
{
|
|
||||||
time_t current = time (NULL);
|
|
||||||
|
|
||||||
if ( newtime == (time_t)-1 || current == newtime)
|
|
||||||
{
|
|
||||||
timemode = NORMAL;
|
|
||||||
timewarp = 0;
|
|
||||||
}
|
|
||||||
else if (freeze)
|
|
||||||
{
|
|
||||||
timemode = FROZEN;
|
|
||||||
timewarp = current;
|
|
||||||
}
|
|
||||||
else if (newtime > current)
|
|
||||||
{
|
|
||||||
timemode = FUTURE;
|
|
||||||
timewarp = newtime - current;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
timemode = PAST;
|
|
||||||
timewarp = current - newtime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Returns true when we are in timewarp mode */
|
|
||||||
int
|
|
||||||
gnupg_faked_time_p (void)
|
|
||||||
{
|
|
||||||
return timemode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* This function is used by gpg because OpenPGP defines the timestamp
|
|
||||||
as an unsigned 32 bit value. */
|
|
||||||
u32
|
|
||||||
make_timestamp (void)
|
|
||||||
{
|
|
||||||
time_t t = gnupg_get_time ();
|
|
||||||
|
|
||||||
if (t == (time_t)-1)
|
|
||||||
log_fatal ("gnupg_get_time() failed\n");
|
|
||||||
return (u32)t;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Scan a date string and return a timestamp.
|
|
||||||
* The only supported format is "yyyy-mm-dd"
|
|
||||||
* Returns 0 for an invalid date.
|
|
||||||
*/
|
|
||||||
u32
|
|
||||||
scan_isodatestr( const char *string )
|
|
||||||
{
|
|
||||||
int year, month, day;
|
|
||||||
struct tm tmbuf;
|
|
||||||
time_t stamp;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if( strlen(string) != 10 || string[4] != '-' || string[7] != '-' )
|
|
||||||
return 0;
|
|
||||||
for( i=0; i < 4; i++ )
|
|
||||||
if( !digitp (string+i) )
|
|
||||||
return 0;
|
|
||||||
if( !digitp (string+5) || !digitp(string+6) )
|
|
||||||
return 0;
|
|
||||||
if( !digitp(string+8) || !digitp(string+9) )
|
|
||||||
return 0;
|
|
||||||
year = atoi(string);
|
|
||||||
month = atoi(string+5);
|
|
||||||
day = atoi(string+8);
|
|
||||||
/* some basic checks */
|
|
||||||
if( year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 )
|
|
||||||
return 0;
|
|
||||||
memset( &tmbuf, 0, sizeof tmbuf );
|
|
||||||
tmbuf.tm_mday = day;
|
|
||||||
tmbuf.tm_mon = month-1;
|
|
||||||
tmbuf.tm_year = year - 1900;
|
|
||||||
tmbuf.tm_isdst = -1;
|
|
||||||
stamp = mktime( &tmbuf );
|
|
||||||
if( stamp == (time_t)-1 )
|
|
||||||
return 0;
|
|
||||||
return stamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
u32
|
|
||||||
add_days_to_timestamp( u32 stamp, u16 days )
|
|
||||||
{
|
|
||||||
return stamp + days*86400L;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Return a string with a time value in the form: x Y, n D, n H
|
|
||||||
*/
|
|
||||||
|
|
||||||
const char *
|
|
||||||
strtimevalue( u32 value )
|
|
||||||
{
|
|
||||||
static char buffer[30];
|
|
||||||
unsigned int years, days, hours, minutes;
|
|
||||||
|
|
||||||
value /= 60;
|
|
||||||
minutes = value % 60;
|
|
||||||
value /= 60;
|
|
||||||
hours = value % 24;
|
|
||||||
value /= 24;
|
|
||||||
days = value % 365;
|
|
||||||
value /= 365;
|
|
||||||
years = value;
|
|
||||||
|
|
||||||
sprintf(buffer,"%uy%ud%uh%um", years, days, hours, minutes );
|
|
||||||
if( years )
|
|
||||||
return buffer;
|
|
||||||
if( days )
|
|
||||||
return strchr( buffer, 'y' ) + 1;
|
|
||||||
return strchr( buffer, 'd' ) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Note: this function returns GMT
|
|
||||||
*/
|
|
||||||
const char *
|
|
||||||
strtimestamp( u32 stamp )
|
|
||||||
{
|
|
||||||
static char buffer[11+5];
|
|
||||||
struct tm *tp;
|
|
||||||
time_t atime = stamp;
|
|
||||||
|
|
||||||
if (atime < 0) {
|
|
||||||
strcpy (buffer, "????" "-??" "-??");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
tp = gmtime( &atime );
|
|
||||||
sprintf(buffer,"%04d-%02d-%02d",
|
|
||||||
1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
|
|
||||||
}
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Note: this function returns local time
|
|
||||||
*/
|
|
||||||
const char *
|
|
||||||
asctimestamp( u32 stamp )
|
|
||||||
{
|
|
||||||
static char buffer[50];
|
|
||||||
#if defined (HAVE_STRFTIME) && defined (HAVE_NL_LANGINFO)
|
|
||||||
static char fmt[50];
|
|
||||||
#endif
|
|
||||||
struct tm *tp;
|
|
||||||
time_t atime = stamp;
|
|
||||||
|
|
||||||
if (atime < 0) {
|
|
||||||
strcpy (buffer, "????" "-??" "-??");
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
tp = localtime( &atime );
|
|
||||||
#ifdef HAVE_STRFTIME
|
|
||||||
#if defined(HAVE_NL_LANGINFO)
|
|
||||||
mem2str( fmt, nl_langinfo(D_T_FMT), DIM(fmt)-3 );
|
|
||||||
if( strstr( fmt, "%Z" ) == NULL )
|
|
||||||
strcat( fmt, " %Z");
|
|
||||||
/* NOTE: gcc -Wformat-noliteral will complain here. I have
|
|
||||||
found no way to suppress this warning .*/
|
|
||||||
strftime (buffer, DIM(buffer)-1, fmt, tp);
|
|
||||||
#else
|
|
||||||
/* FIXME: we should check whether the locale appends a " %Z"
|
|
||||||
* These locales from glibc don't put the " %Z":
|
|
||||||
* fi_FI hr_HR ja_JP lt_LT lv_LV POSIX ru_RU ru_SU sv_FI sv_SE zh_CN
|
|
||||||
*/
|
|
||||||
strftime( buffer, DIM(buffer)-1, "%c %Z", tp );
|
|
||||||
#endif
|
|
||||||
buffer[DIM(buffer)-1] = 0;
|
|
||||||
#else
|
|
||||||
mem2str( buffer, asctime(tp), DIM(buffer) );
|
|
||||||
#endif
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
|||||||
/* i18n.h
|
|
||||||
* Copyright (C) 1998, 2001 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 GNUPG_COMMON_I18N_H
|
|
||||||
#define GNUPG_COMMON_I18N_H
|
|
||||||
|
|
||||||
#ifdef USE_SIMPLE_GETTEXT
|
|
||||||
int set_gettext_file( const char *filename );
|
|
||||||
const char *gettext( const char *msgid );
|
|
||||||
# define _(a) gettext (a)
|
|
||||||
# define N_(a) (a)
|
|
||||||
#else
|
|
||||||
# ifdef HAVE_LOCALE_H
|
|
||||||
# include <locale.h>
|
|
||||||
# endif
|
|
||||||
# ifdef ENABLE_NLS
|
|
||||||
# include <libintl.h>
|
|
||||||
# define _(a) gettext (a)
|
|
||||||
# ifdef gettext_noop
|
|
||||||
# define N_(a) gettext_noop (a)
|
|
||||||
# else
|
|
||||||
# define N_(a) (a)
|
|
||||||
# endif
|
|
||||||
# else
|
|
||||||
# define _(a) (a)
|
|
||||||
# define N_(a) (a)
|
|
||||||
# endif
|
|
||||||
#endif /*!USE_SIMPLE_GETTEXT*/
|
|
||||||
|
|
||||||
#endif /*GNUPG_COMMON_I18N_H*/
|
|
2415
common/iobuf.c
2415
common/iobuf.c
File diff suppressed because it is too large
Load Diff
170
common/iobuf.h
170
common/iobuf.h
@ -1,170 +0,0 @@
|
|||||||
/* iobuf.h - I/O buffer
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2003 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 GNUPG_COMMON_IOBUF_H
|
|
||||||
#define GNUPG_COMMON_IOBUF_H
|
|
||||||
|
|
||||||
#include "../include/types.h" /* fixme: should be moved elsewhere. */
|
|
||||||
|
|
||||||
|
|
||||||
#define DBG_IOBUF iobuf_debug_mode
|
|
||||||
|
|
||||||
|
|
||||||
#define IOBUFCTRL_INIT 1
|
|
||||||
#define IOBUFCTRL_FREE 2
|
|
||||||
#define IOBUFCTRL_UNDERFLOW 3
|
|
||||||
#define IOBUFCTRL_FLUSH 4
|
|
||||||
#define IOBUFCTRL_DESC 5
|
|
||||||
#define IOBUFCTRL_CANCEL 6
|
|
||||||
#define IOBUFCTRL_USER 16
|
|
||||||
|
|
||||||
typedef struct iobuf_struct *iobuf_t;
|
|
||||||
|
|
||||||
/* fixme: we should hide most of this stuff */
|
|
||||||
struct iobuf_struct
|
|
||||||
{
|
|
||||||
int use; /* 1 input , 2 output, 3 temp */
|
|
||||||
off_t nlimit;
|
|
||||||
off_t nbytes; /* used together with nlimit */
|
|
||||||
off_t ntotal; /* total bytes read (position of stream) */
|
|
||||||
int nofast; /* used by the iobuf_get() */
|
|
||||||
void *directfp;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
size_t size; /* allocated size */
|
|
||||||
size_t start; /* number of invalid bytes at the begin of the buffer */
|
|
||||||
size_t len; /* currently filled to this size */
|
|
||||||
byte *buf;
|
|
||||||
}
|
|
||||||
d;
|
|
||||||
int filter_eof;
|
|
||||||
int error;
|
|
||||||
int (*filter) (void *opaque, int control,
|
|
||||||
iobuf_t chain, byte * buf, size_t * len);
|
|
||||||
void *filter_ov; /* value for opaque */
|
|
||||||
int filter_ov_owner;
|
|
||||||
char *real_fname;
|
|
||||||
iobuf_t chain; /* next iobuf used for i/o if any
|
|
||||||
(passed to filter) */
|
|
||||||
int no, subno;
|
|
||||||
const char *desc;
|
|
||||||
void *opaque; /* can be used to hold any information
|
|
||||||
this value is copied to all
|
|
||||||
instances */
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
size_t size; /* allocated size */
|
|
||||||
size_t start; /* number of invalid bytes at the
|
|
||||||
begin of the buffer */
|
|
||||||
size_t len; /* currently filled to this size */
|
|
||||||
byte *buf;
|
|
||||||
}
|
|
||||||
unget;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef EXTERN_UNLESS_MAIN_MODULE
|
|
||||||
#if defined (__riscos__) && !defined (INCLUDED_BY_MAIN_MODULE)
|
|
||||||
#define EXTERN_UNLESS_MAIN_MODULE extern
|
|
||||||
#else
|
|
||||||
#define EXTERN_UNLESS_MAIN_MODULE
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
EXTERN_UNLESS_MAIN_MODULE int iobuf_debug_mode;
|
|
||||||
|
|
||||||
void iobuf_enable_special_filenames (int yes);
|
|
||||||
iobuf_t iobuf_alloc (int use, size_t bufsize);
|
|
||||||
iobuf_t iobuf_temp (void);
|
|
||||||
iobuf_t iobuf_temp_with_content (const char *buffer, size_t length);
|
|
||||||
iobuf_t iobuf_open (const char *fname);
|
|
||||||
iobuf_t iobuf_fdopen (int fd, const char *mode);
|
|
||||||
iobuf_t iobuf_sockopen (int fd, const char *mode);
|
|
||||||
iobuf_t iobuf_create (const char *fname);
|
|
||||||
iobuf_t iobuf_append (const char *fname);
|
|
||||||
iobuf_t iobuf_openrw (const char *fname);
|
|
||||||
int iobuf_ioctl (iobuf_t a, int cmd, int intval, void *ptrval);
|
|
||||||
int iobuf_close (iobuf_t iobuf);
|
|
||||||
int iobuf_cancel (iobuf_t iobuf);
|
|
||||||
|
|
||||||
int iobuf_push_filter (iobuf_t a, int (*f) (void *opaque, int control,
|
|
||||||
iobuf_t chain, byte * buf,
|
|
||||||
size_t * len), void *ov);
|
|
||||||
int iobuf_push_filter2 (iobuf_t a,
|
|
||||||
int (*f) (void *opaque, int control, iobuf_t chain,
|
|
||||||
byte * buf, size_t * len), void *ov,
|
|
||||||
int rel_ov);
|
|
||||||
int iobuf_flush (iobuf_t a);
|
|
||||||
void iobuf_clear_eof (iobuf_t a);
|
|
||||||
#define iobuf_set_error(a) do { (a)->error = 1; } while(0)
|
|
||||||
#define iobuf_error(a) ((a)->error)
|
|
||||||
|
|
||||||
void iobuf_set_limit (iobuf_t a, off_t nlimit);
|
|
||||||
|
|
||||||
off_t iobuf_tell (iobuf_t a);
|
|
||||||
int iobuf_seek (iobuf_t a, off_t newpos);
|
|
||||||
|
|
||||||
int iobuf_readbyte (iobuf_t a);
|
|
||||||
int iobuf_read (iobuf_t a, byte * buf, unsigned buflen);
|
|
||||||
unsigned iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
|
|
||||||
unsigned *length_of_buffer, unsigned *max_length);
|
|
||||||
int iobuf_peek (iobuf_t a, byte * buf, unsigned buflen);
|
|
||||||
int iobuf_writebyte (iobuf_t a, unsigned c);
|
|
||||||
int iobuf_write (iobuf_t a, byte * buf, unsigned buflen);
|
|
||||||
int iobuf_writestr (iobuf_t a, const char *buf);
|
|
||||||
|
|
||||||
void iobuf_flush_temp (iobuf_t temp);
|
|
||||||
int iobuf_write_temp (iobuf_t a, iobuf_t temp);
|
|
||||||
size_t iobuf_temp_to_buffer (iobuf_t a, byte * buffer, size_t buflen);
|
|
||||||
void iobuf_unget_and_close_temp (iobuf_t a, iobuf_t temp);
|
|
||||||
|
|
||||||
off_t iobuf_get_filelength (iobuf_t a);
|
|
||||||
#define IOBUF_FILELENGTH_LIMIT 0xffffffff
|
|
||||||
const char *iobuf_get_real_fname (iobuf_t a);
|
|
||||||
const char *iobuf_get_fname (iobuf_t a);
|
|
||||||
|
|
||||||
void iobuf_set_block_mode (iobuf_t a, size_t n);
|
|
||||||
void iobuf_set_partial_block_mode (iobuf_t a, size_t len);
|
|
||||||
int iobuf_in_block_mode (iobuf_t a);
|
|
||||||
|
|
||||||
int iobuf_translate_file_handle (int fd, int for_write);
|
|
||||||
|
|
||||||
|
|
||||||
/* get a byte form the iobuf; must check for eof prior to this function
|
|
||||||
* this function returns values in the range 0 .. 255 or -1 to indicate EOF
|
|
||||||
* iobuf_get_noeof() does not return -1 to indicate EOF, but masks the
|
|
||||||
* returned value to be in the range 0 ..255.
|
|
||||||
*/
|
|
||||||
#define iobuf_get(a) \
|
|
||||||
( ((a)->nofast || (a)->d.start >= (a)->d.len )? \
|
|
||||||
iobuf_readbyte((a)) : ( (a)->nbytes++, (a)->d.buf[(a)->d.start++] ) )
|
|
||||||
#define iobuf_get_noeof(a) (iobuf_get((a))&0xff)
|
|
||||||
|
|
||||||
/* write a byte to the iobuf and return true on write error
|
|
||||||
* This macro does only write the low order byte
|
|
||||||
*/
|
|
||||||
#define iobuf_put(a,c) iobuf_writebyte(a,c)
|
|
||||||
|
|
||||||
#define iobuf_where(a) "[don't know]"
|
|
||||||
#define iobuf_id(a) ((a)->no)
|
|
||||||
|
|
||||||
#define iobuf_get_temp_buffer(a) ( (a)->d.buf )
|
|
||||||
#define iobuf_get_temp_length(a) ( (a)->d.len )
|
|
||||||
#define iobuf_is_temp(a) ( (a)->use == 3 )
|
|
||||||
|
|
||||||
#endif /*GNUPG_COMMON_IOBUF_H*/
|
|
@ -1,29 +0,0 @@
|
|||||||
/* isascii.c - Replacement for isascii.
|
|
||||||
* Copyright (C) 2002 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int
|
|
||||||
isascii (int c)
|
|
||||||
{
|
|
||||||
return (((c) & ~0x7f) == 0);
|
|
||||||
}
|
|
@ -1,105 +0,0 @@
|
|||||||
/* maperror.c - Error mapping
|
|
||||||
* Copyright (C) 2001, 2002 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <ksba.h>
|
|
||||||
#include <assuan.h>
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
#include "errors.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* Map Assuan error code ERR to an GPG_ERR_ code. We need to
|
|
||||||
distinguish between genuine (and legacy) Assuan error codes and
|
|
||||||
application error codes shared with all GnuPG modules. The rule is
|
|
||||||
simple: All errors with a gpg_err_source of UNKNOWN are genuine
|
|
||||||
Assuan codes all others are passed verbatim through. */
|
|
||||||
gpg_error_t
|
|
||||||
map_assuan_err (int err)
|
|
||||||
{
|
|
||||||
gpg_err_code_t ec;
|
|
||||||
|
|
||||||
if (gpg_err_source (err))
|
|
||||||
return err;
|
|
||||||
|
|
||||||
switch (err)
|
|
||||||
{
|
|
||||||
case -1: ec = GPG_ERR_EOF; break;
|
|
||||||
case 0: ec = 0; break;
|
|
||||||
|
|
||||||
case ASSUAN_Canceled: ec = GPG_ERR_CANCELED; break;
|
|
||||||
case ASSUAN_Invalid_Index: ec = GPG_ERR_INV_INDEX; break;
|
|
||||||
|
|
||||||
case ASSUAN_Not_Implemented: ec = GPG_ERR_NOT_IMPLEMENTED; break;
|
|
||||||
case ASSUAN_Server_Fault: ec = GPG_ERR_ASSUAN_SERVER_FAULT; break;
|
|
||||||
case ASSUAN_No_Public_Key: ec = GPG_ERR_NO_PUBKEY; break;
|
|
||||||
case ASSUAN_No_Secret_Key: ec = GPG_ERR_NO_SECKEY; break;
|
|
||||||
|
|
||||||
case ASSUAN_Cert_Revoked: ec = GPG_ERR_CERT_REVOKED; break;
|
|
||||||
case ASSUAN_No_CRL_For_Cert: ec = GPG_ERR_NO_CRL_KNOWN; break;
|
|
||||||
case ASSUAN_CRL_Too_Old: ec = GPG_ERR_CRL_TOO_OLD; break;
|
|
||||||
|
|
||||||
case ASSUAN_Not_Trusted: ec = GPG_ERR_NOT_TRUSTED; break;
|
|
||||||
|
|
||||||
case ASSUAN_Card_Error: ec = GPG_ERR_CARD; break;
|
|
||||||
case ASSUAN_Invalid_Card: ec = GPG_ERR_INV_CARD; break;
|
|
||||||
case ASSUAN_No_PKCS15_App: ec = GPG_ERR_NO_PKCS15_APP; break;
|
|
||||||
case ASSUAN_Card_Not_Present: ec= GPG_ERR_CARD_NOT_PRESENT; break;
|
|
||||||
case ASSUAN_Not_Confirmed: ec = GPG_ERR_NOT_CONFIRMED; break;
|
|
||||||
case ASSUAN_Invalid_Id: ec = GPG_ERR_INV_ID; break;
|
|
||||||
|
|
||||||
case ASSUAN_Locale_Problem: ec = GPG_ERR_LOCALE_PROBLEM; break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ec = err < 100? GPG_ERR_ASSUAN_SERVER_FAULT : GPG_ERR_ASSUAN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return gpg_err_make (GPG_ERR_SOURCE_UNKNOWN, ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Map GPG_xERR_xx error codes to Assuan status codes */
|
|
||||||
int
|
|
||||||
map_to_assuan_status (int rc)
|
|
||||||
{
|
|
||||||
gpg_err_code_t ec = gpg_err_code (rc);
|
|
||||||
gpg_err_source_t es = gpg_err_source (rc);
|
|
||||||
|
|
||||||
if (!rc)
|
|
||||||
return 0;
|
|
||||||
if (!es)
|
|
||||||
{
|
|
||||||
es = GPG_ERR_SOURCE_USER_4; /* This should not happen, but we
|
|
||||||
need to make sure to pass a new
|
|
||||||
Assuan errorcode along. */
|
|
||||||
log_debug ("map_to_assuan_status called with no error source\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ec == -1)
|
|
||||||
ec = GPG_ERR_NO_DATA; /* That used to be ASSUAN_No_Data_Available. */
|
|
||||||
|
|
||||||
return gpg_err_make (es, ec);
|
|
||||||
}
|
|
@ -1,89 +0,0 @@
|
|||||||
/* membuf.c - A simple implementation of a dynamic buffer
|
|
||||||
* Copyright (C) 2001, 2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "membuf.h"
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* A simple implementation of a dynamic buffer. Use init_membuf() to
|
|
||||||
create a buffer, put_membuf to append bytes and get_membuf to
|
|
||||||
release and return the buffer. Allocation errors are detected but
|
|
||||||
only returned at the final get_membuf(), this helps not to clutter
|
|
||||||
the code with out of core checks. */
|
|
||||||
|
|
||||||
void
|
|
||||||
init_membuf (membuf_t *mb, int initiallen)
|
|
||||||
{
|
|
||||||
mb->len = 0;
|
|
||||||
mb->size = initiallen;
|
|
||||||
mb->out_of_core = 0;
|
|
||||||
mb->buf = xtrymalloc (initiallen);
|
|
||||||
if (!mb->buf)
|
|
||||||
mb->out_of_core = errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
put_membuf (membuf_t *mb, const void *buf, size_t len)
|
|
||||||
{
|
|
||||||
if (mb->out_of_core)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (mb->len + len >= mb->size)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
mb->size += len + 1024;
|
|
||||||
p = xtryrealloc (mb->buf, mb->size);
|
|
||||||
if (!p)
|
|
||||||
{
|
|
||||||
mb->out_of_core = errno;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mb->buf = p;
|
|
||||||
}
|
|
||||||
memcpy (mb->buf + mb->len, buf, len);
|
|
||||||
mb->len += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *
|
|
||||||
get_membuf (membuf_t *mb, size_t *len)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
if (mb->out_of_core)
|
|
||||||
{
|
|
||||||
xfree (mb->buf);
|
|
||||||
mb->buf = NULL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = mb->buf;
|
|
||||||
*len = mb->len;
|
|
||||||
mb->buf = NULL;
|
|
||||||
mb->out_of_core = ENOMEM; /* hack to make sure it won't get reused. */
|
|
||||||
return p;
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
/* membuf.h - A simple implementation of a dynamic buffer
|
|
||||||
* Copyright (C) 2001, 2003 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 GNUPG_COMMON_MEMBUF_H
|
|
||||||
#define GNUPG_COMMON_MEMBUF_H
|
|
||||||
|
|
||||||
/* The definition of the structure is private, we only need it here,
|
|
||||||
so it can be allocated on the stack. */
|
|
||||||
struct private_membuf_s {
|
|
||||||
size_t len;
|
|
||||||
size_t size;
|
|
||||||
char *buf;
|
|
||||||
int out_of_core;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct private_membuf_s membuf_t;
|
|
||||||
|
|
||||||
|
|
||||||
void init_membuf (membuf_t *mb, int initiallen);
|
|
||||||
void put_membuf (membuf_t *mb, const void *buf, size_t len);
|
|
||||||
void *get_membuf (membuf_t *mb, size_t *len);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*GNUPG_COMMON_MEMBUF_H*/
|
|
@ -1,127 +0,0 @@
|
|||||||
/* miscellaneous.c - Stuff not fitting elsewhere
|
|
||||||
* Copyright (C) 2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
#include "iobuf.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* Decide whether the filename is stdout or a real filename and return
|
|
||||||
* an appropriate string. */
|
|
||||||
const char *
|
|
||||||
print_fname_stdout (const char *s)
|
|
||||||
{
|
|
||||||
if( !s || (*s == '-' && !s[1]) )
|
|
||||||
return "[stdout]";
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Decide whether the filename is stdin or a real filename and return
|
|
||||||
* an appropriate string. */
|
|
||||||
const char *
|
|
||||||
print_fname_stdin (const char *s)
|
|
||||||
{
|
|
||||||
if( !s || (*s == '-' && !s[1]) )
|
|
||||||
return "[stdin]";
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
print_string( FILE *fp, const byte *p, size_t n, int delim )
|
|
||||||
{
|
|
||||||
print_sanitized_buffer (fp, p, n, delim);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
print_utf8_string2 ( FILE *fp, const byte *p, size_t n, int delim )
|
|
||||||
{
|
|
||||||
print_sanitized_utf8_buffer (fp, p, n, delim);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
print_utf8_string( FILE *fp, const byte *p, size_t n )
|
|
||||||
{
|
|
||||||
print_utf8_string2 (fp, p, n, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
make_printable_string( const byte *p, size_t n, int delim )
|
|
||||||
{
|
|
||||||
return sanitize_buffer (p, n, delim);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if the file is compressed.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
is_file_compressed (const char *s, int *ret_rc)
|
|
||||||
{
|
|
||||||
iobuf_t a;
|
|
||||||
byte buf[4];
|
|
||||||
int i, rc = 0;
|
|
||||||
|
|
||||||
struct magic_compress_s {
|
|
||||||
size_t len;
|
|
||||||
byte magic[4];
|
|
||||||
} magic[] = {
|
|
||||||
{ 3, { 0x42, 0x5a, 0x68, 0x00 } }, /* bzip2 */
|
|
||||||
{ 3, { 0x1f, 0x8b, 0x08, 0x00 } }, /* gzip */
|
|
||||||
{ 4, { 0x50, 0x4b, 0x03, 0x04 } }, /* (pk)zip */
|
|
||||||
};
|
|
||||||
|
|
||||||
if ( !s || (*s == '-' && !s[1]) || !ret_rc )
|
|
||||||
return 0; /* We can't check stdin or no file was given */
|
|
||||||
|
|
||||||
a = iobuf_open( s );
|
|
||||||
if ( a == NULL ) {
|
|
||||||
*ret_rc = gpg_error_from_errno (errno);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( iobuf_get_filelength( a ) < 4 ) {
|
|
||||||
*ret_rc = 0;
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( iobuf_read( a, buf, 4 ) == -1 ) {
|
|
||||||
*ret_rc = a->error;
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( i = 0; i < DIM( magic ); i++ ) {
|
|
||||||
if ( !memcmp( buf, magic[i].magic, magic[i].len ) ) {
|
|
||||||
*ret_rc = 0;
|
|
||||||
rc = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
leave:
|
|
||||||
iobuf_close( a );
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
|||||||
/* mkdtemp.c - libc replacement function
|
|
||||||
* Copyright (C) 2001 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This is a replacement function for mkdtemp in case the platform
|
|
||||||
we're building on (like mine!) doesn't have it. */
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <gcrypt.h>
|
|
||||||
|
|
||||||
#ifdef MKDIR_TAKES_ONE_ARG
|
|
||||||
# undef mkdir
|
|
||||||
# define mkdir(a,b) mkdir(a)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char *mkdtemp(char *template)
|
|
||||||
{
|
|
||||||
int attempts,idx,count=0;
|
|
||||||
unsigned char *ch;
|
|
||||||
|
|
||||||
idx=strlen(template);
|
|
||||||
|
|
||||||
/* Walk backwards to count all the Xes */
|
|
||||||
while(idx>0 && template[idx-1]=='X')
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
idx--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(count==0)
|
|
||||||
{
|
|
||||||
errno=EINVAL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ch=&template[idx];
|
|
||||||
|
|
||||||
/* Try 4 times to make the temp directory */
|
|
||||||
for(attempts=0;attempts<4;attempts++)
|
|
||||||
{
|
|
||||||
int remaining=count;
|
|
||||||
char *marker=ch;
|
|
||||||
unsigned char *randombits;
|
|
||||||
|
|
||||||
idx=0;
|
|
||||||
|
|
||||||
randombits = gcry_xmalloc (4*remaining);
|
|
||||||
gcry_create_nonce (randombits, 4*remaining);
|
|
||||||
|
|
||||||
while(remaining>1)
|
|
||||||
{
|
|
||||||
sprintf(marker,"%02X",randombits[idx++]);
|
|
||||||
marker+=2;
|
|
||||||
remaining-=2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Any leftover Xes? get_random_bits rounds up to full bytes,
|
|
||||||
so this is safe. */
|
|
||||||
if(remaining>0)
|
|
||||||
sprintf(marker,"%X",randombits[idx]&0xF);
|
|
||||||
|
|
||||||
gcry_free (randombits);
|
|
||||||
|
|
||||||
if(mkdir(template,0700)==0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(attempts==4)
|
|
||||||
return NULL; /* keeps the errno from mkdir, whatever it is */
|
|
||||||
|
|
||||||
return template;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# mkerrors - Extract error strings from errors.h
|
|
||||||
# and create C source for gnupg_strerror
|
|
||||||
# Copyright (C) 2001 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
|
|
||||||
|
|
||||||
cat <<EOF
|
|
||||||
/* Generated automatically by mkerrors */
|
|
||||||
/* Do not edit! */
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "errors.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gnupg_strerror:
|
|
||||||
* @err: Error code
|
|
||||||
*
|
|
||||||
* This function returns a textual representaion of the given
|
|
||||||
* errorcode. If this is an unknown value, a string with the value
|
|
||||||
* is returned (Beware: it is hold in a static buffer).
|
|
||||||
*
|
|
||||||
* Return value: String with the error description.
|
|
||||||
**/
|
|
||||||
const char *
|
|
||||||
gnupg_strerror (int err)
|
|
||||||
{
|
|
||||||
const char *s;
|
|
||||||
static char buf[25];
|
|
||||||
|
|
||||||
switch (err)
|
|
||||||
{
|
|
||||||
EOF
|
|
||||||
|
|
||||||
awk '
|
|
||||||
/GNUPG_No_Error/ { okay=1 }
|
|
||||||
!okay {next}
|
|
||||||
/}/ { exit 0 }
|
|
||||||
/GNUPG_[A-Za-z_]*/ { print_code($1) }
|
|
||||||
|
|
||||||
|
|
||||||
function print_code( s )
|
|
||||||
{
|
|
||||||
printf " case %s: s=\"", s ;
|
|
||||||
gsub(/_/, " ", s );
|
|
||||||
printf "%s\"; break;\n", tolower(substr(s,7));
|
|
||||||
}
|
|
||||||
'
|
|
||||||
|
|
||||||
cat <<EOF
|
|
||||||
default: sprintf (buf, "ec=%d", err ); s=buf; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
EOF
|
|
@ -1,67 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# mkerrtok - Create error tokens from errors.h
|
|
||||||
# and the C source for gnupg_errortoken
|
|
||||||
# Copyright (C) 2001, 2002 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
|
|
||||||
|
|
||||||
cat <<EOF
|
|
||||||
/* Generated automatically by mkerrtok */
|
|
||||||
/* Do not edit! */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gnupg_error_token:
|
|
||||||
* @err: Error code
|
|
||||||
*
|
|
||||||
* This function returns a textual representaion of the given
|
|
||||||
* errorcode. If this is an unknown value, a static string is returned.
|
|
||||||
* This function differs from gnupg_strerror that it yields the string
|
|
||||||
* representation of the macro which is never subject to i18n.
|
|
||||||
*
|
|
||||||
* Return value: String with the error token.
|
|
||||||
**/
|
|
||||||
const char *
|
|
||||||
gnupg_error_token (int err)
|
|
||||||
{
|
|
||||||
const char *s;
|
|
||||||
|
|
||||||
switch (err)
|
|
||||||
{
|
|
||||||
EOF
|
|
||||||
|
|
||||||
awk '
|
|
||||||
/GNUPG_No_Error/ { okay=1 }
|
|
||||||
!okay {next}
|
|
||||||
/}/ { exit 0 }
|
|
||||||
/GNUPG_[A-Za-z_]*/ { print_code($1) }
|
|
||||||
|
|
||||||
|
|
||||||
function print_code( s )
|
|
||||||
{
|
|
||||||
printf " case %s: s=\"", s ;
|
|
||||||
printf "%s\"; break;\n", substr(s,7);
|
|
||||||
}
|
|
||||||
'
|
|
||||||
|
|
||||||
cat <<EOF
|
|
||||||
default: s = "Unknown_Error"; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
EOF
|
|
@ -1,31 +0,0 @@
|
|||||||
/* putc_unlocked.c - Replacement for putc_unlocked.
|
|
||||||
* Copyright (C) 2002 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int
|
|
||||||
putc_unlocked (int c, FILE *stream)
|
|
||||||
{
|
|
||||||
return putc (c, stream);
|
|
||||||
}
|
|
@ -1,99 +0,0 @@
|
|||||||
/* sexp-parse.h - S-Exp helper functions
|
|
||||||
* Copyright (C) 2002, 2003 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 SEXP_PARSE_H
|
|
||||||
#define SEXP_PARSE_H
|
|
||||||
|
|
||||||
#include <gpg-error.h>
|
|
||||||
|
|
||||||
/* Return the length of the next S-Exp part and update the pointer to
|
|
||||||
the first data byte. 0 is returned on error */
|
|
||||||
static inline size_t
|
|
||||||
snext (unsigned char const **buf)
|
|
||||||
{
|
|
||||||
const unsigned char *s;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
s = *buf;
|
|
||||||
for (n=0; *s && *s != ':' && (*s >= '0' && *s <= '9'); s++)
|
|
||||||
n = n*10 + (*s - '0');
|
|
||||||
if (!n || *s != ':')
|
|
||||||
return 0; /* we don't allow empty lengths */
|
|
||||||
*buf = s+1;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip over the S-Expression BUF points to and update BUF to point to
|
|
||||||
the chacter right behind. DEPTH gives the initial number of open
|
|
||||||
lists and may be passed as a positive number to skip over the
|
|
||||||
remainder of an S-Expression if the current position is somewhere
|
|
||||||
in an S-Expression. The function may return an error code if it
|
|
||||||
encounters an impossible conditions */
|
|
||||||
static inline gpg_error_t
|
|
||||||
sskip (unsigned char const **buf, int *depth)
|
|
||||||
{
|
|
||||||
const unsigned char *s = *buf;
|
|
||||||
size_t n;
|
|
||||||
int d = *depth;
|
|
||||||
|
|
||||||
while (d > 0)
|
|
||||||
{
|
|
||||||
if (*s == '(')
|
|
||||||
{
|
|
||||||
d++;
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
else if (*s == ')')
|
|
||||||
{
|
|
||||||
d--;
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!d)
|
|
||||||
return gpg_error (GPG_ERR_INV_SEXP);
|
|
||||||
n = snext (&s);
|
|
||||||
if (!n)
|
|
||||||
return gpg_error (GPG_ERR_INV_SEXP);
|
|
||||||
s += n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*buf = s;
|
|
||||||
*depth = d;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Check whether the the string at the address BUF points to matches
|
|
||||||
the token. Return true on match and update BUF to point behind the
|
|
||||||
token. Return false and dont update tha buffer if it does not
|
|
||||||
match. */
|
|
||||||
static inline int
|
|
||||||
smatch (unsigned char const **buf, size_t buflen, const char *token)
|
|
||||||
{
|
|
||||||
size_t toklen = strlen (token);
|
|
||||||
|
|
||||||
if (buflen != toklen || memcmp (*buf, token, toklen))
|
|
||||||
return 0;
|
|
||||||
*buf += toklen;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /*SEXP_PARSE_H*/
|
|
226
common/signal.c
226
common/signal.c
@ -1,226 +0,0 @@
|
|||||||
/* signal.c - signal handling
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
|
|
||||||
static volatile int caught_fatal_sig;
|
|
||||||
static volatile int caught_sigusr1;
|
|
||||||
static void (*cleanup_fnc)(void);
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
init_one_signal (int sig, RETSIGTYPE (*handler)(int), int check_ign )
|
|
||||||
{
|
|
||||||
#ifndef HAVE_DOSISH_SYSTEM
|
|
||||||
# ifdef HAVE_SIGACTION
|
|
||||||
struct sigaction oact, nact;
|
|
||||||
|
|
||||||
if (check_ign)
|
|
||||||
{
|
|
||||||
/* we don't want to change an IGN handler */
|
|
||||||
sigaction (sig, NULL, &oact );
|
|
||||||
if (oact.sa_handler == SIG_IGN )
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nact.sa_handler = handler;
|
|
||||||
sigemptyset (&nact.sa_mask);
|
|
||||||
nact.sa_flags = 0;
|
|
||||||
sigaction ( sig, &nact, NULL);
|
|
||||||
# else
|
|
||||||
RETSIGTYPE (*ohandler)(int);
|
|
||||||
|
|
||||||
ohandler = signal (sig, handler);
|
|
||||||
if (check_ign && ohandler == SIG_IGN)
|
|
||||||
{
|
|
||||||
/* Change it back if it was already set to IGN */
|
|
||||||
signal (sig, SIG_IGN);
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
#endif /*!HAVE_DOSISH_SYSTEM*/
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
get_signal_name( int signum )
|
|
||||||
{
|
|
||||||
#if defined(SYS_SIGLIST_DECLARED) && defined(NSIG)
|
|
||||||
return (signum >= 0 && signum < NSIG) ? sys_siglist[signum] : "?";
|
|
||||||
#else
|
|
||||||
return "some signal";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static RETSIGTYPE
|
|
||||||
got_fatal_signal (int sig)
|
|
||||||
{
|
|
||||||
const char *s;
|
|
||||||
|
|
||||||
if (caught_fatal_sig)
|
|
||||||
raise (sig);
|
|
||||||
caught_fatal_sig = 1;
|
|
||||||
|
|
||||||
if (cleanup_fnc)
|
|
||||||
cleanup_fnc ();
|
|
||||||
/* better don't translate these messages */
|
|
||||||
write (2, "\n", 1 );
|
|
||||||
s = log_get_prefix (NULL);
|
|
||||||
if (s)
|
|
||||||
write(2, s, strlen (s));
|
|
||||||
write (2, ": ", 2 );
|
|
||||||
s = get_signal_name(sig);
|
|
||||||
write (2, s, strlen(s) );
|
|
||||||
write (2, " caught ... exiting\n", 20);
|
|
||||||
|
|
||||||
/* reset action to default action and raise signal again */
|
|
||||||
init_one_signal (sig, SIG_DFL, 0);
|
|
||||||
/* fixme: remove_lockfiles ();*/
|
|
||||||
#ifdef __riscos__
|
|
||||||
close_fds ();
|
|
||||||
#endif /* __riscos__ */
|
|
||||||
raise( sig );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static RETSIGTYPE
|
|
||||||
got_usr_signal (int sig)
|
|
||||||
{
|
|
||||||
caught_sigusr1 = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
gnupg_init_signals (int mode, void (*fast_cleanup)(void))
|
|
||||||
{
|
|
||||||
assert (!mode);
|
|
||||||
|
|
||||||
cleanup_fnc = fast_cleanup;
|
|
||||||
#ifndef HAVE_DOSISH_SYSTEM
|
|
||||||
init_one_signal (SIGINT, got_fatal_signal, 1 );
|
|
||||||
init_one_signal (SIGHUP, got_fatal_signal, 1 );
|
|
||||||
init_one_signal (SIGTERM, got_fatal_signal, 1 );
|
|
||||||
init_one_signal (SIGQUIT, got_fatal_signal, 1 );
|
|
||||||
init_one_signal (SIGSEGV, got_fatal_signal, 1 );
|
|
||||||
init_one_signal (SIGUSR1, got_usr_signal, 0 );
|
|
||||||
init_one_signal (SIGPIPE, SIG_IGN, 0 );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
gnupg_pause_on_sigusr (int which)
|
|
||||||
{
|
|
||||||
#ifndef HAVE_DOSISH_SYSTEM
|
|
||||||
# ifdef HAVE_SIGPROCMASK
|
|
||||||
sigset_t mask, oldmask;
|
|
||||||
|
|
||||||
assert (which == 1);
|
|
||||||
sigemptyset( &mask );
|
|
||||||
sigaddset( &mask, SIGUSR1 );
|
|
||||||
|
|
||||||
sigprocmask( SIG_BLOCK, &mask, &oldmask );
|
|
||||||
while (!caught_sigusr1)
|
|
||||||
sigsuspend (&oldmask);
|
|
||||||
caught_sigusr1 = 0;
|
|
||||||
sigprocmask (SIG_UNBLOCK, &mask, NULL);
|
|
||||||
# else
|
|
||||||
assert (which == 1);
|
|
||||||
sighold (SIGUSR1);
|
|
||||||
while (!caught_sigusr1)
|
|
||||||
sigpause(SIGUSR1);
|
|
||||||
caught_sigusr1 = 0;
|
|
||||||
sigrelease(SIGUSR1);
|
|
||||||
# endif /*!HAVE_SIGPROCMASK*/
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
do_block( int block )
|
|
||||||
{
|
|
||||||
#ifndef HAVE_DOSISH_SYSTEM
|
|
||||||
static int is_blocked;
|
|
||||||
#ifdef HAVE_SIGPROCMASK
|
|
||||||
static sigset_t oldmask;
|
|
||||||
|
|
||||||
if (block)
|
|
||||||
{
|
|
||||||
sigset_t newmask;
|
|
||||||
|
|
||||||
if (is_blocked)
|
|
||||||
log_bug ("signals are already blocked\n");
|
|
||||||
sigfillset( &newmask );
|
|
||||||
sigprocmask( SIG_BLOCK, &newmask, &oldmask );
|
|
||||||
is_blocked = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!is_blocked)
|
|
||||||
log_bug("signals are not blocked\n");
|
|
||||||
sigprocmask (SIG_SETMASK, &oldmask, NULL);
|
|
||||||
is_blocked = 0;
|
|
||||||
}
|
|
||||||
#else /*!HAVE_SIGPROCMASK*/
|
|
||||||
static void (*disposition[MAXSIG])();
|
|
||||||
int sig;
|
|
||||||
|
|
||||||
if (block)
|
|
||||||
{
|
|
||||||
if (is_blocked)
|
|
||||||
log_bug("signals are already blocked\n");
|
|
||||||
for (sig=1; sig < MAXSIG; sig++)
|
|
||||||
{
|
|
||||||
disposition[sig] = sigset (sig, SIG_HOLD);
|
|
||||||
}
|
|
||||||
is_blocked = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!is_blocked)
|
|
||||||
log_bug ("signals are not blocked\n");
|
|
||||||
for (sig=1; sig < MAXSIG; sig++) {
|
|
||||||
sigset (sig, disposition[sig]);
|
|
||||||
}
|
|
||||||
is_blocked = 0;
|
|
||||||
}
|
|
||||||
#endif /*!HAVE_SIGPROCMASK*/
|
|
||||||
#endif /*HAVE_DOSISH_SYSTEM*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
gnupg_block_all_signals ()
|
|
||||||
{
|
|
||||||
do_block(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
gnupg_unblock_all_signals ()
|
|
||||||
{
|
|
||||||
do_block(0);
|
|
||||||
}
|
|
@ -1,493 +0,0 @@
|
|||||||
/* simple-pwquery.c - A simple password query cleint for gpg-agent
|
|
||||||
* Copyright (C) 2002 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This module is intended as a standalone client implementation to
|
|
||||||
gpg-agent's GET_PASSPHRASE command. In particular it does not use
|
|
||||||
the Assuan library and can only cope with an already running
|
|
||||||
gpg-agent. Some stuff is configurable in the header file. */
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#ifdef HAVE_LOCALE_H
|
|
||||||
#include <locale.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SIMPLE_PWQUERY_IMPLEMENTATION 1
|
|
||||||
#include "simple-pwquery.h"
|
|
||||||
|
|
||||||
#if defined(SPWQ_USE_LOGGING) && !defined(HAVE_JNLIB_LOGGING)
|
|
||||||
# undef SPWQ_USE_LOGGING
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _
|
|
||||||
#define _(a) (a)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined (hexdigitp) && !defined (xtoi_2)
|
|
||||||
#define digitp(p) (*(p) >= '0' && *(p) <= '9')
|
|
||||||
#define hexdigitp(a) (digitp (a) \
|
|
||||||
|| (*(a) >= 'A' && *(a) <= 'F') \
|
|
||||||
|| (*(a) >= 'a' && *(a) <= 'f'))
|
|
||||||
#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
|
|
||||||
*(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
|
|
||||||
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Write NBYTES of BUF to file descriptor FD. */
|
|
||||||
static int
|
|
||||||
writen (int fd, const void *buf, size_t nbytes)
|
|
||||||
{
|
|
||||||
size_t nleft = nbytes;
|
|
||||||
int nwritten;
|
|
||||||
|
|
||||||
while (nleft > 0)
|
|
||||||
{
|
|
||||||
nwritten = write( fd, buf, nleft );
|
|
||||||
if (nwritten < 0)
|
|
||||||
{
|
|
||||||
if (errno == EINTR)
|
|
||||||
nwritten = 0;
|
|
||||||
else {
|
|
||||||
#ifdef SPWQ_USE_LOGGING
|
|
||||||
log_error ("write failed: %s\n", strerror (errno));
|
|
||||||
#endif
|
|
||||||
return SPWQ_IO_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nleft -= nwritten;
|
|
||||||
buf = (const char*)buf + nwritten;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Read an entire line and return number of bytes read. */
|
|
||||||
static int
|
|
||||||
readline (int fd, char *buf, size_t buflen)
|
|
||||||
{
|
|
||||||
size_t nleft = buflen;
|
|
||||||
char *p;
|
|
||||||
int nread = 0;
|
|
||||||
|
|
||||||
while (nleft > 0)
|
|
||||||
{
|
|
||||||
int n = read (fd, buf, nleft);
|
|
||||||
if (n < 0)
|
|
||||||
{
|
|
||||||
if (errno == EINTR)
|
|
||||||
continue;
|
|
||||||
return -(SPWQ_IO_ERROR);
|
|
||||||
}
|
|
||||||
else if (!n)
|
|
||||||
{
|
|
||||||
return -(SPWQ_PROTOCOL_ERROR); /* incomplete line */
|
|
||||||
}
|
|
||||||
p = buf;
|
|
||||||
nleft -= n;
|
|
||||||
buf += n;
|
|
||||||
nread += n;
|
|
||||||
|
|
||||||
for (; n && *p != '\n'; n--, p++)
|
|
||||||
;
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
break; /* at least one full line available - that's enough.
|
|
||||||
This function is just a simple implementation, so
|
|
||||||
it is okay to forget about pending bytes */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nread;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Send an option to the agent */
|
|
||||||
static int
|
|
||||||
agent_send_option (int fd, const char *name, const char *value)
|
|
||||||
{
|
|
||||||
char buf[200];
|
|
||||||
int nread;
|
|
||||||
char *line;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
line = spwq_malloc (7 + strlen (name) + 1 + strlen (value) + 2);
|
|
||||||
if (!line)
|
|
||||||
return SPWQ_OUT_OF_CORE;
|
|
||||||
strcpy (stpcpy (stpcpy (stpcpy (
|
|
||||||
stpcpy (line, "OPTION "), name), "="), value), "\n");
|
|
||||||
i = writen (fd, line, strlen (line));
|
|
||||||
spwq_free (line);
|
|
||||||
if (i)
|
|
||||||
return i;
|
|
||||||
|
|
||||||
/* get response */
|
|
||||||
nread = readline (fd, buf, DIM(buf)-1);
|
|
||||||
if (nread < 0)
|
|
||||||
return -nread;
|
|
||||||
if (nread < 3)
|
|
||||||
return SPWQ_PROTOCOL_ERROR;
|
|
||||||
|
|
||||||
if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n'))
|
|
||||||
return 0; /* okay */
|
|
||||||
|
|
||||||
return SPWQ_ERR_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Send all available options to the agent. */
|
|
||||||
static int
|
|
||||||
agent_send_all_options (int fd)
|
|
||||||
{
|
|
||||||
char *dft_display = NULL;
|
|
||||||
char *dft_ttyname = NULL;
|
|
||||||
char *dft_ttytype = NULL;
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
dft_display = getenv ("DISPLAY");
|
|
||||||
if (dft_display)
|
|
||||||
{
|
|
||||||
if ((rc = agent_send_option (fd, "display", dft_display)))
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
dft_ttyname = getenv ("GPG_TTY");
|
|
||||||
if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
|
|
||||||
dft_ttyname = ttyname (0);
|
|
||||||
if (dft_ttyname && *dft_ttyname)
|
|
||||||
{
|
|
||||||
if ((rc=agent_send_option (fd, "ttyname", dft_ttyname)))
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
dft_ttytype = getenv ("TERM");
|
|
||||||
if (dft_ttyname && dft_ttytype)
|
|
||||||
{
|
|
||||||
if ((rc = agent_send_option (fd, "ttytype", dft_ttytype)))
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HAVE_SETLOCALE)
|
|
||||||
{
|
|
||||||
char *old_lc = NULL;
|
|
||||||
char *dft_lc = NULL;
|
|
||||||
|
|
||||||
#if defined(LC_CTYPE)
|
|
||||||
old_lc = setlocale (LC_CTYPE, NULL);
|
|
||||||
if (old_lc)
|
|
||||||
{
|
|
||||||
char *p = spwq_malloc (strlen (old_lc)+1);
|
|
||||||
if (!p)
|
|
||||||
return SPWQ_OUT_OF_CORE;
|
|
||||||
strcpy (p, old_lc);
|
|
||||||
old_lc = p;
|
|
||||||
}
|
|
||||||
dft_lc = setlocale (LC_CTYPE, "");
|
|
||||||
if (dft_ttyname && dft_lc)
|
|
||||||
rc = agent_send_option (fd, "lc-ctype", dft_lc);
|
|
||||||
if (old_lc)
|
|
||||||
{
|
|
||||||
setlocale (LC_CTYPE, old_lc);
|
|
||||||
spwq_free (old_lc);
|
|
||||||
}
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(LC_MESSAGES)
|
|
||||||
old_lc = setlocale (LC_MESSAGES, NULL);
|
|
||||||
if (old_lc)
|
|
||||||
{
|
|
||||||
char *p = spwq_malloc (strlen (old_lc)+1);
|
|
||||||
if (!p)
|
|
||||||
return SPWQ_OUT_OF_CORE;
|
|
||||||
strcpy (p, old_lc);
|
|
||||||
old_lc = p;
|
|
||||||
}
|
|
||||||
dft_lc = setlocale (LC_MESSAGES, "");
|
|
||||||
if (dft_ttyname && dft_lc)
|
|
||||||
rc = agent_send_option (fd, "lc-messages", dft_lc);
|
|
||||||
if (old_lc)
|
|
||||||
{
|
|
||||||
setlocale (LC_MESSAGES, old_lc);
|
|
||||||
spwq_free (old_lc);
|
|
||||||
}
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif /*HAVE_SETLOCALE*/
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Try to open a connection to the agent, send all options and return
|
|
||||||
the file descriptor for the connection. Return -1 in case of
|
|
||||||
error. */
|
|
||||||
static int
|
|
||||||
agent_open (int *rfd)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
int fd;
|
|
||||||
char *infostr, *p;
|
|
||||||
struct sockaddr_un client_addr;
|
|
||||||
size_t len;
|
|
||||||
int prot;
|
|
||||||
char line[200];
|
|
||||||
int nread;
|
|
||||||
|
|
||||||
*rfd = -1;
|
|
||||||
infostr = getenv ( "GPG_AGENT_INFO" );
|
|
||||||
if ( !infostr || !*infostr )
|
|
||||||
{
|
|
||||||
#ifdef SPWQ_USE_LOGGING
|
|
||||||
log_error (_("gpg-agent is not available in this session\n"));
|
|
||||||
#endif
|
|
||||||
return SPWQ_NO_AGENT;
|
|
||||||
}
|
|
||||||
p = spwq_malloc (strlen (infostr)+1);
|
|
||||||
if (!p)
|
|
||||||
return SPWQ_OUT_OF_CORE;
|
|
||||||
strcpy (p, infostr);
|
|
||||||
infostr = p;
|
|
||||||
|
|
||||||
if ( !(p = strchr ( infostr, ':')) || p == infostr
|
|
||||||
|| (p-infostr)+1 >= sizeof client_addr.sun_path )
|
|
||||||
{
|
|
||||||
#ifdef SPWQ_USE_LOGGING
|
|
||||||
log_error ( _("malformed GPG_AGENT_INFO environment variable\n"));
|
|
||||||
#endif
|
|
||||||
return SPWQ_NO_AGENT;
|
|
||||||
}
|
|
||||||
*p++ = 0;
|
|
||||||
|
|
||||||
while (*p && *p != ':')
|
|
||||||
p++;
|
|
||||||
prot = *p? atoi (p+1) : 0;
|
|
||||||
if ( prot != 1)
|
|
||||||
{
|
|
||||||
#ifdef SPWQ_USE_LOGGING
|
|
||||||
log_error (_("gpg-agent protocol version %d is not supported\n"),prot);
|
|
||||||
#endif
|
|
||||||
return SPWQ_PROTOCOL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 )
|
|
||||||
{
|
|
||||||
#ifdef SPWQ_USE_LOGGING
|
|
||||||
log_error ("can't create socket: %s\n", strerror(errno) );
|
|
||||||
#endif
|
|
||||||
return SPWQ_SYS_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset (&client_addr, 0, sizeof client_addr);
|
|
||||||
client_addr.sun_family = AF_UNIX;
|
|
||||||
strcpy (client_addr.sun_path, infostr);
|
|
||||||
len = (offsetof (struct sockaddr_un, sun_path)
|
|
||||||
+ strlen(client_addr.sun_path) + 1);
|
|
||||||
|
|
||||||
if (connect (fd, (struct sockaddr*)&client_addr, len ) == -1)
|
|
||||||
{
|
|
||||||
#ifdef SPWQ_USE_LOGGING
|
|
||||||
log_error ( _("can't connect to `%s': %s\n"), infostr, strerror (errno));
|
|
||||||
#endif
|
|
||||||
close (fd );
|
|
||||||
return SPWQ_IO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
nread = readline (fd, line, DIM(line));
|
|
||||||
if (nread < 3 || !(line[0] == 'O' && line[1] == 'K'
|
|
||||||
&& (line[2] == '\n' || line[2] == ' ')) )
|
|
||||||
{
|
|
||||||
#ifdef SPWQ_USE_LOGGING
|
|
||||||
log_error ( _("communication problem with gpg-agent\n"));
|
|
||||||
#endif
|
|
||||||
close (fd );
|
|
||||||
return SPWQ_PROTOCOL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = agent_send_all_options (fd);
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
#ifdef SPWQ_USE_LOGGING
|
|
||||||
log_error (_("problem setting the gpg-agent options\n"));
|
|
||||||
#endif
|
|
||||||
close (fd);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
*rfd = fd;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Copy text to BUFFER and escape as required. Return a pointer to
|
|
||||||
the end of the new buffer. NOte that BUFFER must be large enough
|
|
||||||
to keep the entire text; allocataing it 3 times the size of TEXT
|
|
||||||
is sufficient. */
|
|
||||||
static char *
|
|
||||||
copy_and_escape (char *buffer, const char *text)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
const unsigned char *s = text;
|
|
||||||
char *p = buffer;
|
|
||||||
|
|
||||||
|
|
||||||
for (i=0; s[i]; i++)
|
|
||||||
{
|
|
||||||
if (s[i] < ' ' || s[i] == '+')
|
|
||||||
{
|
|
||||||
sprintf (p, "%%%02X", s[i]);
|
|
||||||
p += 3;
|
|
||||||
}
|
|
||||||
else if (s[i] == ' ')
|
|
||||||
*p++ = '+';
|
|
||||||
else
|
|
||||||
*p++ = s[i];
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Ask the gpg-agent for a passphrase and present the user with a
|
|
||||||
DESCRIPTION, a PROMPT and optiaonlly with a TRYAGAIN extra text.
|
|
||||||
If a CACHEID is not NULL it is used to locate the passphrase in in
|
|
||||||
the cache and store it under this ID. If ERRORCODE is not NULL it
|
|
||||||
should point a variable receiving an errorcode; thsi errocode might
|
|
||||||
be 0 if the user canceled the operation. The function returns NULL
|
|
||||||
to indicate an error. */
|
|
||||||
char *
|
|
||||||
simple_pwquery (const char *cacheid,
|
|
||||||
const char *tryagain,
|
|
||||||
const char *prompt,
|
|
||||||
const char *description,
|
|
||||||
int *errorcode)
|
|
||||||
{
|
|
||||||
int fd = -1;
|
|
||||||
int nread;
|
|
||||||
char *result = NULL;
|
|
||||||
char *pw = NULL;
|
|
||||||
char *p;
|
|
||||||
int rc, i;
|
|
||||||
|
|
||||||
rc = agent_open (&fd);
|
|
||||||
if (rc)
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
if (!cacheid)
|
|
||||||
cacheid = "X";
|
|
||||||
if (!tryagain)
|
|
||||||
tryagain = "X";
|
|
||||||
if (!prompt)
|
|
||||||
prompt = "X";
|
|
||||||
if (!description)
|
|
||||||
description = "X";
|
|
||||||
|
|
||||||
{
|
|
||||||
char *line;
|
|
||||||
/* We allocate 3 times the needed space so that there is enough
|
|
||||||
space for escaping. */
|
|
||||||
line = spwq_malloc (15
|
|
||||||
+ 3*strlen (cacheid) + 1
|
|
||||||
+ 3*strlen (tryagain) + 1
|
|
||||||
+ 3*strlen (prompt) + 1
|
|
||||||
+ 3*strlen (description) + 1
|
|
||||||
+ 2);
|
|
||||||
if (!line)
|
|
||||||
{
|
|
||||||
rc = SPWQ_OUT_OF_CORE;
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
strcpy (line, "GET_PASSPHRASE ");
|
|
||||||
p = line+15;
|
|
||||||
p = copy_and_escape (p, cacheid);
|
|
||||||
*p++ = ' ';
|
|
||||||
p = copy_and_escape (p, tryagain);
|
|
||||||
*p++ = ' ';
|
|
||||||
p = copy_and_escape (p, prompt);
|
|
||||||
*p++ = ' ';
|
|
||||||
p = copy_and_escape (p, description);
|
|
||||||
*p++ = '\n';
|
|
||||||
rc = writen (fd, line, p - line);
|
|
||||||
spwq_free (line);
|
|
||||||
if (rc)
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get response */
|
|
||||||
pw = spwq_secure_malloc (500);
|
|
||||||
nread = readline (fd, pw, 499);
|
|
||||||
if (nread < 0)
|
|
||||||
{
|
|
||||||
rc = -nread;
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
if (nread < 3)
|
|
||||||
{
|
|
||||||
rc = SPWQ_PROTOCOL_ERROR;
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pw[0] == 'O' && pw[1] == 'K' && pw[2] == ' ')
|
|
||||||
{ /* we got a passphrase - convert it back from hex */
|
|
||||||
size_t pwlen = 0;
|
|
||||||
|
|
||||||
for (i=3; i < nread && hexdigitp (pw+i); i+=2)
|
|
||||||
pw[pwlen++] = xtoi_2 (pw+i);
|
|
||||||
pw[pwlen] = 0; /* make a C String */
|
|
||||||
result = pw;
|
|
||||||
pw = NULL;
|
|
||||||
}
|
|
||||||
else if (nread > 7 && !memcmp (pw, "ERR 111", 7)
|
|
||||||
&& (pw[7] == ' ' || pw[7] == '\n') )
|
|
||||||
{
|
|
||||||
#ifdef SPWQ_USE_LOGGING
|
|
||||||
log_info (_("canceled by user\n") );
|
|
||||||
#endif
|
|
||||||
*errorcode = 0; /* canceled */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef SPWQ_USE_LOGGING
|
|
||||||
log_error (_("problem with the agent\n"));
|
|
||||||
#endif
|
|
||||||
rc = SPWQ_ERR_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
leave:
|
|
||||||
if (errorcode)
|
|
||||||
*errorcode = rc;
|
|
||||||
if (fd != -1)
|
|
||||||
close (fd);
|
|
||||||
if (pw)
|
|
||||||
spwq_free (pw);
|
|
||||||
return result;
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
/* simple-pwquery.c - A simple password query cleint for gpg-agent
|
|
||||||
* Copyright (C) 2002 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 SIMPLE_PWQUERY_H
|
|
||||||
#define SIMPLE_PWQUERY_H
|
|
||||||
|
|
||||||
#ifdef SIMPLE_PWQUERY_IMPLEMENTATION /* Begin configuration stuff. */
|
|
||||||
|
|
||||||
/* Include whatever files you need. */
|
|
||||||
#include <gcrypt.h>
|
|
||||||
#include "../jnlib/logging.h"
|
|
||||||
|
|
||||||
/* Try to write error message using the standard log mechanism. The
|
|
||||||
current implementation requires that the HAVE_JNLIB_LOGGING is also
|
|
||||||
defined. */
|
|
||||||
#define SPWQ_USE_LOGGING 1
|
|
||||||
|
|
||||||
/* Memory allocation functions used by the implementation. Note, that
|
|
||||||
the returned value is expected to be freed with
|
|
||||||
spwq_secure_free. */
|
|
||||||
#define spwq_malloc(a) gcry_malloc (a)
|
|
||||||
#define spwq_free(a) gcry_free (a)
|
|
||||||
#define spwq_secure_malloc(a) gcry_malloc_secure (a)
|
|
||||||
#define spwq_secure_free(a) gcry_free (a)
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*SIMPLE_PWQUERY_IMPLEMENTATION*/ /* End configuration stuff. */
|
|
||||||
|
|
||||||
|
|
||||||
/* Ask the gpg-agent for a passphrase and present the user with a
|
|
||||||
DESCRIPTION, a PROMPT and optiaonlly with a TRYAGAIN extra text.
|
|
||||||
If a CACHEID is not NULL it is used to locate the passphrase in in
|
|
||||||
the cache and store it under this ID. If ERRORCODE is not NULL it
|
|
||||||
should point a variable receiving an errorcode; this errocode might
|
|
||||||
be 0 if the user canceled the operation. The function returns NULL
|
|
||||||
to indicate an error. */
|
|
||||||
char *simple_pwquery (const char *cacheid,
|
|
||||||
const char *tryagain,
|
|
||||||
const char *prompt,
|
|
||||||
const char *description,
|
|
||||||
int *errorcode);
|
|
||||||
|
|
||||||
|
|
||||||
#define SPWQ_OUT_OF_CORE 1
|
|
||||||
#define SPWQ_IO_ERROR 2
|
|
||||||
#define SPWQ_PROTOCOL_ERROR 3
|
|
||||||
#define SPWQ_ERR_RESPONSE 4
|
|
||||||
#define SPWQ_NO_AGENT 5
|
|
||||||
#define SPWQ_SYS_ERROR 6
|
|
||||||
#define SPWQ_GENERAL_ERROR 7
|
|
||||||
|
|
||||||
#endif /*SIMPLE_PWQUERY_H*/
|
|
@ -1,230 +0,0 @@
|
|||||||
/* sysutils.c - system helpers
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#ifdef HAVE_STAT
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#endif
|
|
||||||
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
|
|
||||||
#include <asm/sysinfo.h>
|
|
||||||
#include <asm/unistd.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SETRLIMIT
|
|
||||||
#include <time.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#endif
|
|
||||||
#include "util.h"
|
|
||||||
#include "i18n.h"
|
|
||||||
|
|
||||||
#include "sysutils.h"
|
|
||||||
|
|
||||||
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
|
|
||||||
#warning using trap_unaligned
|
|
||||||
static int
|
|
||||||
setsysinfo(unsigned long op, void *buffer, unsigned long size,
|
|
||||||
int *start, void *arg, unsigned long flag)
|
|
||||||
{
|
|
||||||
return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
trap_unaligned(void)
|
|
||||||
{
|
|
||||||
unsigned int buf[2];
|
|
||||||
|
|
||||||
buf[0] = SSIN_UACPROC;
|
|
||||||
buf[1] = UAC_SIGBUS | UAC_NOPRINT;
|
|
||||||
setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void
|
|
||||||
trap_unaligned(void)
|
|
||||||
{ /* dummy */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
disable_core_dumps (void)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_DOSISH_SYSTEM
|
|
||||||
return 0;
|
|
||||||
#else
|
|
||||||
# ifdef HAVE_SETRLIMIT
|
|
||||||
struct rlimit limit;
|
|
||||||
|
|
||||||
/* We only set the current limit unless we were not able to
|
|
||||||
retrieve the old value. */
|
|
||||||
if (getrlimit (RLIMIT_CORE, &limit))
|
|
||||||
limit.rlim_max = 0;
|
|
||||||
limit.rlim_cur = 0;
|
|
||||||
if( !setrlimit (RLIMIT_CORE, &limit) )
|
|
||||||
return 0;
|
|
||||||
if( errno != EINVAL && errno != ENOSYS )
|
|
||||||
log_fatal (_("can't disable core dumps: %s\n"), strerror(errno) );
|
|
||||||
#endif
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
enable_core_dumps (void)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_DOSISH_SYSTEM
|
|
||||||
return 0;
|
|
||||||
#else
|
|
||||||
# ifdef HAVE_SETRLIMIT
|
|
||||||
struct rlimit limit;
|
|
||||||
|
|
||||||
if (getrlimit (RLIMIT_CORE, &limit))
|
|
||||||
return 1;
|
|
||||||
limit.rlim_cur = limit.rlim_max;
|
|
||||||
setrlimit (RLIMIT_CORE, &limit);
|
|
||||||
return 1; /* We always return true because trhis function is
|
|
||||||
merely a debugging aid. */
|
|
||||||
#endif
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Return a string which is used as a kind of process ID */
|
|
||||||
const byte *
|
|
||||||
get_session_marker( size_t *rlen )
|
|
||||||
{
|
|
||||||
static byte marker[SIZEOF_UNSIGNED_LONG*2];
|
|
||||||
static int initialized;
|
|
||||||
|
|
||||||
if ( !initialized ) {
|
|
||||||
volatile ulong aa, bb; /* we really want the uninitialized value */
|
|
||||||
ulong a, b;
|
|
||||||
|
|
||||||
initialized = 1;
|
|
||||||
/* also this marker is guessable it is not easy to use this
|
|
||||||
* for a faked control packet because an attacker does not
|
|
||||||
* have enough control about the time the verification does
|
|
||||||
* take place. Of course, we can add just more random but
|
|
||||||
* than we need the random generator even for verification
|
|
||||||
* tasks - which does not make sense. */
|
|
||||||
a = aa ^ (ulong)getpid();
|
|
||||||
b = bb ^ (ulong)time(NULL);
|
|
||||||
memcpy( marker, &a, SIZEOF_UNSIGNED_LONG );
|
|
||||||
memcpy( marker+SIZEOF_UNSIGNED_LONG, &b, SIZEOF_UNSIGNED_LONG );
|
|
||||||
}
|
|
||||||
*rlen = sizeof(marker);
|
|
||||||
return marker;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if 0 /* not yet needed - Note that this will require inclusion of
|
|
||||||
cmacros.am in Makefile.am */
|
|
||||||
int
|
|
||||||
check_permissions(const char *path,int extension,int checkonly)
|
|
||||||
{
|
|
||||||
#if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
|
|
||||||
char *tmppath;
|
|
||||||
struct stat statbuf;
|
|
||||||
int ret=1;
|
|
||||||
int isdir=0;
|
|
||||||
|
|
||||||
if(opt.no_perm_warn)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if(extension && path[0]!=DIRSEP_C)
|
|
||||||
{
|
|
||||||
if(strchr(path,DIRSEP_C))
|
|
||||||
tmppath=make_filename(path,NULL);
|
|
||||||
else
|
|
||||||
tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
tmppath=m_strdup(path);
|
|
||||||
|
|
||||||
/* It's okay if the file doesn't exist */
|
|
||||||
if(stat(tmppath,&statbuf)!=0)
|
|
||||||
{
|
|
||||||
ret=0;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
isdir=S_ISDIR(statbuf.st_mode);
|
|
||||||
|
|
||||||
/* Per-user files must be owned by the user. Extensions must be
|
|
||||||
owned by the user or root. */
|
|
||||||
if((!extension && statbuf.st_uid != getuid()) ||
|
|
||||||
(extension && statbuf.st_uid!=0 && statbuf.st_uid!=getuid()))
|
|
||||||
{
|
|
||||||
if(!checkonly)
|
|
||||||
log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
|
|
||||||
isdir?"directory":extension?"extension":"file",path);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This works for both directories and files - basically, we don't
|
|
||||||
care what the owner permissions are, so long as the group and
|
|
||||||
other permissions are 0 for per-user files, and non-writable for
|
|
||||||
extensions. */
|
|
||||||
if((extension && (statbuf.st_mode & (S_IWGRP|S_IWOTH)) !=0) ||
|
|
||||||
(!extension && (statbuf.st_mode & (S_IRWXG|S_IRWXO)) != 0))
|
|
||||||
{
|
|
||||||
char *dir;
|
|
||||||
|
|
||||||
/* However, if the directory the directory/file is in is owned
|
|
||||||
by the user and is 700, then this is not a problem.
|
|
||||||
Theoretically, we could walk this test up to the root
|
|
||||||
directory /, but for the sake of sanity, I'm stopping at one
|
|
||||||
level down. */
|
|
||||||
|
|
||||||
dir= make_dirname (tmppath);
|
|
||||||
if(stat(dir,&statbuf)==0 && statbuf.st_uid==getuid() &&
|
|
||||||
S_ISDIR(statbuf.st_mode) && (statbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
|
|
||||||
{
|
|
||||||
xfree (dir);
|
|
||||||
ret=0;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_free(dir);
|
|
||||||
|
|
||||||
if(!checkonly)
|
|
||||||
log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
|
|
||||||
isdir?"directory":extension?"extension":"file",path);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret=0;
|
|
||||||
|
|
||||||
end:
|
|
||||||
m_free(tmppath);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
#endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,31 +0,0 @@
|
|||||||
/* sysutils.h - System utility functions for Gnupg
|
|
||||||
* Copyright (C) 2002 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 GNUPG_COMMON_SYSUTILS_H
|
|
||||||
#define GNUPG_COMMON_SYSUTILS_H
|
|
||||||
|
|
||||||
void trap_unaligned (void);
|
|
||||||
int disable_core_dumps (void);
|
|
||||||
int enable_core_dumps (void);
|
|
||||||
const unsigned char *get_session_marker (size_t *rlen);
|
|
||||||
int check_permissions (const char *path,int extension,int checkonly);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*GNUPG_COMMON_SYSUTILS_H*/
|
|
555
common/ttyio.c
555
common/ttyio.c
@ -1,555 +0,0 @@
|
|||||||
/* ttyio.c - tty i/O functions
|
|
||||||
* Copyright (C) 1998,1999,2000,2001,2002,2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#ifdef HAVE_TCGETATTR
|
|
||||||
#include <termios.h>
|
|
||||||
#else
|
|
||||||
#ifdef HAVE_TERMIO_H
|
|
||||||
/* simulate termios with termio */
|
|
||||||
#include <termio.h>
|
|
||||||
#define termios termio
|
|
||||||
#define tcsetattr ioctl
|
|
||||||
#define TCSAFLUSH TCSETAF
|
|
||||||
#define tcgetattr(A,B) ioctl(A,TCGETA,B)
|
|
||||||
#define HAVE_TCGETATTR
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifdef _WIN32 /* use the odd Win32 functions */
|
|
||||||
#include <windows.h>
|
|
||||||
#ifdef HAVE_TCGETATTR
|
|
||||||
#error mingw32 and termios
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#include <errno.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include "util.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "ttyio.h"
|
|
||||||
|
|
||||||
#define CONTROL_D ('D' - 'A' + 1)
|
|
||||||
|
|
||||||
#ifdef _WIN32 /* use the odd Win32 functions */
|
|
||||||
static struct {
|
|
||||||
HANDLE in, out;
|
|
||||||
} con;
|
|
||||||
#define DEF_INPMODE (ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT \
|
|
||||||
|ENABLE_PROCESSED_INPUT )
|
|
||||||
#define HID_INPMODE (ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT )
|
|
||||||
#define DEF_OUTMODE (ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT)
|
|
||||||
|
|
||||||
#else /* yeah, we have a real OS */
|
|
||||||
static FILE *ttyfp = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int initialized;
|
|
||||||
static int last_prompt_len;
|
|
||||||
static int batchmode;
|
|
||||||
static int no_terminal;
|
|
||||||
|
|
||||||
#ifdef HAVE_TCGETATTR
|
|
||||||
static struct termios termsave;
|
|
||||||
static int restore_termios;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* This is a wrapper around ttyname so that we can use it even when
|
|
||||||
the standard streams are redirected. It figures the name out the
|
|
||||||
first time and returns it in a statically allocated buffer. */
|
|
||||||
const char *
|
|
||||||
tty_get_ttyname (void)
|
|
||||||
{
|
|
||||||
static char *name;
|
|
||||||
|
|
||||||
/* On a GNU system ctermid() always return /dev/tty, so this does
|
|
||||||
not make much sense - however if it is ever changed we do the
|
|
||||||
Right Thing now. */
|
|
||||||
#ifdef HAVE_CTERMID
|
|
||||||
static int got_name;
|
|
||||||
|
|
||||||
if (!got_name)
|
|
||||||
{
|
|
||||||
const char *s;
|
|
||||||
s = ctermid (NULL);
|
|
||||||
if (s)
|
|
||||||
name = strdup (s);
|
|
||||||
got_name = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* Assume the staandrd tty on memory error or when tehre is no
|
|
||||||
certmid. */
|
|
||||||
return name? name : "/dev/tty";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_TCGETATTR
|
|
||||||
static void
|
|
||||||
cleanup(void)
|
|
||||||
{
|
|
||||||
if( restore_termios ) {
|
|
||||||
restore_termios = 0; /* do it prios in case it is interrupted again */
|
|
||||||
if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
|
|
||||||
log_error("tcsetattr() failed: %s\n", strerror(errno) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
|
||||||
init_ttyfp(void)
|
|
||||||
{
|
|
||||||
if( initialized )
|
|
||||||
return;
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
{
|
|
||||||
SECURITY_ATTRIBUTES sa;
|
|
||||||
|
|
||||||
memset(&sa, 0, sizeof(sa));
|
|
||||||
sa.nLength = sizeof(sa);
|
|
||||||
sa.bInheritHandle = TRUE;
|
|
||||||
con.out = CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE,
|
|
||||||
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
|
||||||
&sa, OPEN_EXISTING, 0, 0 );
|
|
||||||
if( con.out == INVALID_HANDLE_VALUE )
|
|
||||||
log_fatal("open(CONOUT$) failed: rc=%d", (int)GetLastError() );
|
|
||||||
memset(&sa, 0, sizeof(sa));
|
|
||||||
sa.nLength = sizeof(sa);
|
|
||||||
sa.bInheritHandle = TRUE;
|
|
||||||
con.in = CreateFileA( "CONIN$", GENERIC_READ|GENERIC_WRITE,
|
|
||||||
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
|
||||||
&sa, OPEN_EXISTING, 0, 0 );
|
|
||||||
if( con.in == INVALID_HANDLE_VALUE )
|
|
||||||
log_fatal("open(CONIN$) failed: rc=%d", (int)GetLastError() );
|
|
||||||
}
|
|
||||||
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 = batchmode? stderr : fopen (tty_get_ttyname (), "r+");
|
|
||||||
if( !ttyfp ) {
|
|
||||||
log_error("cannot open `%s': %s\n", tty_get_ttyname (),
|
|
||||||
strerror(errno) );
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_TCGETATTR
|
|
||||||
atexit( cleanup );
|
|
||||||
#endif
|
|
||||||
initialized = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
tty_batchmode( int onoff )
|
|
||||||
{
|
|
||||||
int old = batchmode;
|
|
||||||
if( onoff != -1 )
|
|
||||||
batchmode = onoff;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
tty_no_terminal(int onoff)
|
|
||||||
{
|
|
||||||
int old = no_terminal;
|
|
||||||
no_terminal = onoff ? 1 : 0;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
tty_printf( const char *fmt, ... )
|
|
||||||
{
|
|
||||||
va_list arg_ptr;
|
|
||||||
|
|
||||||
if (no_terminal)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( !initialized )
|
|
||||||
init_ttyfp();
|
|
||||||
|
|
||||||
va_start( arg_ptr, fmt ) ;
|
|
||||||
#ifdef _WIN32
|
|
||||||
{
|
|
||||||
char *buf = NULL;
|
|
||||||
int n;
|
|
||||||
DWORD nwritten;
|
|
||||||
|
|
||||||
n = vasprintf(&buf, fmt, arg_ptr);
|
|
||||||
if( !buf )
|
|
||||||
log_bug("vasprintf() failed\n");
|
|
||||||
|
|
||||||
if( !WriteConsoleA( con.out, buf, n, &nwritten, NULL ) )
|
|
||||||
log_fatal("WriteConsole failed: rc=%d", (int)GetLastError() );
|
|
||||||
if( n != nwritten )
|
|
||||||
log_fatal("WriteConsole failed: %d != %d\n", n, (int)nwritten );
|
|
||||||
last_prompt_len += n;
|
|
||||||
xfree (buf);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
|
|
||||||
fflush(ttyfp);
|
|
||||||
#endif
|
|
||||||
va_end(arg_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Same as tty_printf but if FP is not NULL, behave like a regualr
|
|
||||||
fprintf. */
|
|
||||||
void
|
|
||||||
tty_fprintf (FILE *fp, const char *fmt, ... )
|
|
||||||
{
|
|
||||||
va_list arg_ptr;
|
|
||||||
|
|
||||||
if (fp)
|
|
||||||
{
|
|
||||||
va_start (arg_ptr, fmt) ;
|
|
||||||
vfprintf (fp, fmt, arg_ptr );
|
|
||||||
va_end (arg_ptr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (no_terminal)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( !initialized )
|
|
||||||
init_ttyfp();
|
|
||||||
|
|
||||||
va_start( arg_ptr, fmt ) ;
|
|
||||||
#ifdef _WIN32
|
|
||||||
{
|
|
||||||
char *buf = NULL;
|
|
||||||
int n;
|
|
||||||
DWORD nwritten;
|
|
||||||
|
|
||||||
n = vasprintf(&buf, fmt, arg_ptr);
|
|
||||||
if( !buf )
|
|
||||||
log_bug("vasprintf() failed\n");
|
|
||||||
|
|
||||||
if( !WriteConsoleA( con.out, buf, n, &nwritten, NULL ) )
|
|
||||||
log_fatal("WriteConsole failed: rc=%d", (int)GetLastError() );
|
|
||||||
if( n != nwritten )
|
|
||||||
log_fatal("WriteConsole failed: %d != %d\n", n, (int)nwritten );
|
|
||||||
last_prompt_len += n;
|
|
||||||
xfree (buf);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
|
|
||||||
fflush(ttyfp);
|
|
||||||
#endif
|
|
||||||
va_end(arg_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Print a string, but filter all control characters out.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
tty_print_string ( const byte *p, size_t n )
|
|
||||||
{
|
|
||||||
if (no_terminal)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( !initialized )
|
|
||||||
init_ttyfp();
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
/* not so effective, change it if you want */
|
|
||||||
for( ; n; n--, p++ )
|
|
||||||
if( iscntrl( *p ) ) {
|
|
||||||
if( *p == '\n' )
|
|
||||||
tty_printf("\\n");
|
|
||||||
else if( !*p )
|
|
||||||
tty_printf("\\0");
|
|
||||||
else
|
|
||||||
tty_printf("\\x%02x", *p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
tty_printf("%c", *p);
|
|
||||||
#else
|
|
||||||
for( ; n; n--, p++ )
|
|
||||||
if( iscntrl( *p ) ) {
|
|
||||||
putc('\\', ttyfp);
|
|
||||||
if( *p == '\n' )
|
|
||||||
putc('n', ttyfp);
|
|
||||||
else if( !*p )
|
|
||||||
putc('0', ttyfp);
|
|
||||||
else
|
|
||||||
fprintf(ttyfp, "x%02x", *p );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
putc(*p, ttyfp);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
tty_print_utf8_string2( const byte *p, size_t n, size_t max_n )
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
char *buf;
|
|
||||||
|
|
||||||
if (no_terminal)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* we can handle plain ascii simpler, so check for it first */
|
|
||||||
for(i=0; i < n; i++ ) {
|
|
||||||
if( p[i] & 0x80 )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if( i < n ) {
|
|
||||||
buf = utf8_to_native( p, n, 0 );
|
|
||||||
if( max_n && (strlen( buf ) > max_n )) {
|
|
||||||
buf[max_n] = 0;
|
|
||||||
}
|
|
||||||
/*(utf8 conversion already does the control character quoting)*/
|
|
||||||
tty_printf("%s", buf );
|
|
||||||
xfree( buf );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if( max_n && (n > max_n) ) {
|
|
||||||
n = max_n;
|
|
||||||
}
|
|
||||||
tty_print_string( p, n );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
tty_print_utf8_string( const byte *p, size_t n )
|
|
||||||
{
|
|
||||||
tty_print_utf8_string2( p, n, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static char *
|
|
||||||
do_get( const char *prompt, int hidden )
|
|
||||||
{
|
|
||||||
char *buf;
|
|
||||||
#ifndef __riscos__
|
|
||||||
byte cbuf[1];
|
|
||||||
#endif
|
|
||||||
int c, n, i;
|
|
||||||
|
|
||||||
if( batchmode ) {
|
|
||||||
log_error("Sorry, we are in batchmode - can't get input\n");
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (no_terminal) {
|
|
||||||
log_error("Sorry, no terminal at all requested - can't get input\n");
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !initialized )
|
|
||||||
init_ttyfp();
|
|
||||||
|
|
||||||
last_prompt_len = 0;
|
|
||||||
tty_printf( "%s", prompt );
|
|
||||||
buf = xmalloc((n=50));
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
#ifdef _WIN32 /* windoze version */
|
|
||||||
if( hidden )
|
|
||||||
SetConsoleMode(con.in, HID_INPMODE );
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
DWORD nread;
|
|
||||||
|
|
||||||
if( !ReadConsoleA( con.in, cbuf, 1, &nread, NULL ) )
|
|
||||||
log_fatal("ReadConsole failed: rc=%d", (int)GetLastError() );
|
|
||||||
if( !nread )
|
|
||||||
continue;
|
|
||||||
if( *cbuf == '\n' )
|
|
||||||
break;
|
|
||||||
|
|
||||||
if( !hidden )
|
|
||||||
last_prompt_len++;
|
|
||||||
c = *cbuf;
|
|
||||||
if( c == '\t' )
|
|
||||||
c = ' ';
|
|
||||||
else if( c > 0xa0 )
|
|
||||||
; /* we don't allow 0xa0, as this is a protected blank which may
|
|
||||||
* confuse the user */
|
|
||||||
else if( iscntrl(c) )
|
|
||||||
continue;
|
|
||||||
if( !(i < n-1) ) {
|
|
||||||
n += 50;
|
|
||||||
buf = xrealloc (buf, n);
|
|
||||||
}
|
|
||||||
buf[i++] = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( hidden )
|
|
||||||
SetConsoleMode(con.in, DEF_INPMODE );
|
|
||||||
|
|
||||||
#elif defined(__riscos__)
|
|
||||||
do {
|
|
||||||
c = riscos_getchar();
|
|
||||||
if (c == 0xa || c == 0xd) { /* Return || Enter */
|
|
||||||
c = (int) '\n';
|
|
||||||
} else if (c == 0x8 || c == 0x7f) { /* Backspace || Delete */
|
|
||||||
if (i>0) {
|
|
||||||
i--;
|
|
||||||
if (!hidden) {
|
|
||||||
last_prompt_len--;
|
|
||||||
fputc(8, ttyfp);
|
|
||||||
fputc(32, ttyfp);
|
|
||||||
fputc(8, ttyfp);
|
|
||||||
fflush(ttyfp);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fputc(7, ttyfp);
|
|
||||||
fflush(ttyfp);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
} else if (c == (int) '\t') { /* Tab */
|
|
||||||
c = ' ';
|
|
||||||
} else if (c > 0xa0) {
|
|
||||||
; /* we don't allow 0xa0, as this is a protected blank which may
|
|
||||||
* confuse the user */
|
|
||||||
} else if (iscntrl(c)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(!(i < n-1)) {
|
|
||||||
n += 50;
|
|
||||||
buf = xrealloc (buf, n);
|
|
||||||
}
|
|
||||||
buf[i++] = c;
|
|
||||||
if (!hidden) {
|
|
||||||
last_prompt_len++;
|
|
||||||
fputc(c, ttyfp);
|
|
||||||
fflush(ttyfp);
|
|
||||||
}
|
|
||||||
} while (c != '\n');
|
|
||||||
i = (i>0) ? i-1 : 0;
|
|
||||||
#else /* unix version */
|
|
||||||
if( hidden ) {
|
|
||||||
#ifdef HAVE_TCGETATTR
|
|
||||||
struct termios term;
|
|
||||||
|
|
||||||
if( tcgetattr(fileno(ttyfp), &termsave) )
|
|
||||||
log_fatal("tcgetattr() failed: %s\n", strerror(errno) );
|
|
||||||
restore_termios = 1;
|
|
||||||
term = termsave;
|
|
||||||
term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
|
|
||||||
if( tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) )
|
|
||||||
log_fatal("tcsetattr() failed: %s\n", strerror(errno) );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fixme: How can we avoid that the \n is echoed w/o disabling
|
|
||||||
* canonical mode - w/o this kill_prompt can't work */
|
|
||||||
while( read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n' ) {
|
|
||||||
if( !hidden )
|
|
||||||
last_prompt_len++;
|
|
||||||
c = *cbuf;
|
|
||||||
if( c == CONTROL_D )
|
|
||||||
log_info("control d found\n");
|
|
||||||
if( c == '\t' )
|
|
||||||
c = ' ';
|
|
||||||
else if( c > 0xa0 )
|
|
||||||
; /* we don't allow 0xa0, as this is a protected blank which may
|
|
||||||
* confuse the user */
|
|
||||||
else if( iscntrl(c) )
|
|
||||||
continue;
|
|
||||||
if( !(i < n-1) ) {
|
|
||||||
n += 50;
|
|
||||||
buf = xrealloc (buf, n );
|
|
||||||
}
|
|
||||||
buf[i++] = c;
|
|
||||||
}
|
|
||||||
if( *cbuf != '\n' ) {
|
|
||||||
buf[0] = CONTROL_D;
|
|
||||||
i = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if( hidden ) {
|
|
||||||
#ifdef HAVE_TCGETATTR
|
|
||||||
if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
|
|
||||||
log_error("tcsetattr() failed: %s\n", strerror(errno) );
|
|
||||||
restore_termios = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif /* end unix version */
|
|
||||||
buf[i] = 0;
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char *
|
|
||||||
tty_get( const char *prompt )
|
|
||||||
{
|
|
||||||
return do_get( prompt, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
tty_get_hidden( const char *prompt )
|
|
||||||
{
|
|
||||||
return do_get( prompt, 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
tty_kill_prompt()
|
|
||||||
{
|
|
||||||
if ( no_terminal )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( !initialized )
|
|
||||||
init_ttyfp();
|
|
||||||
|
|
||||||
if( batchmode )
|
|
||||||
last_prompt_len = 0;
|
|
||||||
if( !last_prompt_len )
|
|
||||||
return;
|
|
||||||
#ifdef _WIN32
|
|
||||||
tty_printf("\r%*s\r", last_prompt_len, "");
|
|
||||||
#else
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
putc('\r', ttyfp);
|
|
||||||
for(i=0; i < last_prompt_len; i ++ )
|
|
||||||
putc(' ', ttyfp);
|
|
||||||
putc('\r', ttyfp);
|
|
||||||
fflush(ttyfp);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
last_prompt_len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
tty_get_answer_is_yes( const char *prompt )
|
|
||||||
{
|
|
||||||
int yes;
|
|
||||||
char *p = tty_get( prompt );
|
|
||||||
tty_kill_prompt();
|
|
||||||
yes = answer_is_yes(p);
|
|
||||||
xfree(p);
|
|
||||||
return yes;
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
/* ttyio.h
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2003 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 GNUPG_COMMON_TTYIO_H
|
|
||||||
#define GNUPG_COMMON_TTYIO_H
|
|
||||||
|
|
||||||
const char *tty_get_ttyname (void);
|
|
||||||
int tty_batchmode (int onoff);
|
|
||||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
|
|
||||||
void tty_printf (const char *fmt, ... )
|
|
||||||
__attribute__ ((format (printf,1,2)));
|
|
||||||
void tty_fprintf (FILE *fp, const char *fmt, ... )
|
|
||||||
__attribute__ ((format (printf,2,3)));
|
|
||||||
#else
|
|
||||||
void tty_printf (const char *fmt, ... );
|
|
||||||
void tty_fprintf (FILE *fp, const char *fmt, ... );
|
|
||||||
#endif
|
|
||||||
void tty_print_string (const unsigned char *p, size_t n);
|
|
||||||
void tty_print_utf8_string (const unsigned char *p, size_t n);
|
|
||||||
void tty_print_utf8_string2 (const unsigned char *p, size_t n, size_t max_n);
|
|
||||||
char *tty_get (const char *prompt);
|
|
||||||
char *tty_get_hidden (const char *prompt);
|
|
||||||
void tty_kill_prompt (void);
|
|
||||||
int tty_get_answer_is_yes (const char *prompt);
|
|
||||||
int tty_no_terminal (int onoff);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*GNUPG_COMMON_TTYIO_H*/
|
|
171
common/util.h
171
common/util.h
@ -1,171 +0,0 @@
|
|||||||
/* util.h - Utility functions for GnuPG
|
|
||||||
* Copyright (C) 2001, 2002, 2003, 2004 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 GNUPG_COMMON_UTIL_H
|
|
||||||
#define GNUPG_COMMON_UTIL_H
|
|
||||||
|
|
||||||
#include <gcrypt.h> /* We need this for the memory function protos. */
|
|
||||||
#include <time.h> /* We need time_t. */
|
|
||||||
#include <gpg-error.h> /* we need gpg-error_t. */
|
|
||||||
|
|
||||||
/* to pass hash functions to libksba we need to cast it */
|
|
||||||
#define HASH_FNC ((void (*)(void *, const void*,size_t))gcry_md_write)
|
|
||||||
|
|
||||||
/* get all the stuff from jnlib */
|
|
||||||
#include "../jnlib/logging.h"
|
|
||||||
#include "../jnlib/argparse.h"
|
|
||||||
#include "../jnlib/stringhelp.h"
|
|
||||||
#include "../jnlib/mischelp.h"
|
|
||||||
#include "../jnlib/strlist.h"
|
|
||||||
#include "../jnlib/dotlock.h"
|
|
||||||
#include "../jnlib/utf8conv.h"
|
|
||||||
|
|
||||||
/* Handy malloc macros - please use only them. */
|
|
||||||
#define xtrymalloc(a) gcry_malloc ((a))
|
|
||||||
#define xtrymalloc_secure(a) gcry_malloc_secure ((a))
|
|
||||||
#define xtrycalloc(a,b) gcry_calloc ((a),(b))
|
|
||||||
#define xtrycalloc_secure(a,b) gcry_calloc_secure ((a),(b))
|
|
||||||
#define xtryrealloc(a,b) gcry_realloc ((a),(b))
|
|
||||||
#define xtrystrdup(a) gcry_strdup ((a))
|
|
||||||
#define xfree(a) gcry_free ((a))
|
|
||||||
|
|
||||||
#define xmalloc(a) gcry_xmalloc ((a))
|
|
||||||
#define xmalloc_secure(a) gcry_xmalloc_secure ((a))
|
|
||||||
#define xcalloc(a,b) gcry_xcalloc ((a),(b))
|
|
||||||
#define xcalloc_secure(a,b) gcry_xcalloc_secure ((a),(b))
|
|
||||||
#define xrealloc(a,b) gcry_xrealloc ((a),(b))
|
|
||||||
#define xstrdup(a) gcry_xstrdup ((a))
|
|
||||||
|
|
||||||
|
|
||||||
/* A type to hold the ISO time. Note that this this is the same as
|
|
||||||
the the KSBA type ksba_isotime_t. */
|
|
||||||
typedef char gnupg_isotime_t[16];
|
|
||||||
|
|
||||||
|
|
||||||
/*-- maperror.c --*/
|
|
||||||
int map_kbx_err (int err);
|
|
||||||
gpg_error_t map_assuan_err (int err);
|
|
||||||
int map_to_assuan_status (int rc);
|
|
||||||
|
|
||||||
/*-- gettime.c --*/
|
|
||||||
time_t gnupg_get_time (void);
|
|
||||||
void gnupg_get_isotime (gnupg_isotime_t timebuf);
|
|
||||||
void gnupg_set_time (time_t newtime, int freeze);
|
|
||||||
int gnupg_faked_time_p (void);
|
|
||||||
u32 make_timestamp (void);
|
|
||||||
u32 scan_isodatestr (const char *string);
|
|
||||||
u32 add_days_to_timestamp (u32 stamp, u16 days);
|
|
||||||
const char *strtimevalue (u32 stamp);
|
|
||||||
const char *strtimestamp (u32 stamp); /* GMT */
|
|
||||||
const char *asctimestamp (u32 stamp); /* localized */
|
|
||||||
|
|
||||||
|
|
||||||
/* Copy one iso ddate to another, this is inline so that we can do a
|
|
||||||
sanity check. */
|
|
||||||
static inline void
|
|
||||||
gnupg_copy_time (gnupg_isotime_t d, const gnupg_isotime_t s)
|
|
||||||
{
|
|
||||||
if (*s && (strlen (s) != 15 || s[8] != 'T'))
|
|
||||||
BUG();
|
|
||||||
strcpy (d, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-- signal.c --*/
|
|
||||||
void gnupg_init_signals (int mode, void (*fast_cleanup)(void));
|
|
||||||
void gnupg_pause_on_sigusr (int which);
|
|
||||||
void gnupg_block_all_signals (void);
|
|
||||||
void gnupg_unblock_all_signals (void);
|
|
||||||
|
|
||||||
/*-- yesno.c --*/
|
|
||||||
int answer_is_yes (const char *s);
|
|
||||||
int answer_is_yes_no_default (const char *s, int def_answer);
|
|
||||||
int answer_is_yes_no_quit (const char *s);
|
|
||||||
|
|
||||||
/*-- xreadline.c --*/
|
|
||||||
ssize_t read_line (FILE *fp,
|
|
||||||
char **addr_of_buffer, size_t *length_of_buffer,
|
|
||||||
size_t *max_length);
|
|
||||||
|
|
||||||
|
|
||||||
/*-- b64enc.c --*/
|
|
||||||
struct b64state
|
|
||||||
{
|
|
||||||
unsigned int flags;
|
|
||||||
int idx;
|
|
||||||
int quad_count;
|
|
||||||
FILE *fp;
|
|
||||||
char *title;
|
|
||||||
unsigned char radbuf[4];
|
|
||||||
};
|
|
||||||
gpg_error_t b64enc_start (struct b64state *state, FILE *fp, const char *title);
|
|
||||||
gpg_error_t b64enc_write (struct b64state *state,
|
|
||||||
const void *buffer, size_t nbytes);
|
|
||||||
gpg_error_t b64enc_finish (struct b64state *state);
|
|
||||||
|
|
||||||
|
|
||||||
/*-- miscellaneous.c --*/
|
|
||||||
|
|
||||||
/* Same as asprintf but return an allocated buffer suitable to be
|
|
||||||
freed using xfree. This function simply dies on memory failure,
|
|
||||||
thus no extra check is required. */
|
|
||||||
char *xasprintf (const char *fmt, ...) JNLIB_GCC_A_PRINTF(1,2);
|
|
||||||
|
|
||||||
const char *print_fname_stdout (const char *s);
|
|
||||||
const char *print_fname_stdin (const char *s);
|
|
||||||
void print_string (FILE *fp, const byte *p, size_t n, int delim);
|
|
||||||
void print_utf8_string2 ( FILE *fp, const byte *p, size_t n, int delim);
|
|
||||||
void print_utf8_string (FILE *fp, const byte *p, size_t n);
|
|
||||||
char *make_printable_string (const byte *p, size_t n, int delim);
|
|
||||||
|
|
||||||
int is_file_compressed (const char *s, int *ret_rc);
|
|
||||||
|
|
||||||
|
|
||||||
/*-- replacement functions from funcname.c --*/
|
|
||||||
#if !HAVE_VASPRINTF
|
|
||||||
#include <stdarg.h>
|
|
||||||
int vasprintf (char **result, const char *format, va_list args);
|
|
||||||
int asprintf (char **result, const char *format, ...) JNLIB_GCC_A_PRINTF(2,3);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-- some macros to replace ctype ones and avoid locale problems --*/
|
|
||||||
#define spacep(p) (*(p) == ' ' || *(p) == '\t')
|
|
||||||
#define digitp(p) (*(p) >= '0' && *(p) <= '9')
|
|
||||||
#define hexdigitp(a) (digitp (a) \
|
|
||||||
|| (*(a) >= 'A' && *(a) <= 'F') \
|
|
||||||
|| (*(a) >= 'a' && *(a) <= 'f'))
|
|
||||||
/* Note this isn't identical to a C locale isspace() without \f and
|
|
||||||
\v, but works for the purposes used here. */
|
|
||||||
#define ascii_isspace(a) ((a)==' ' || (a)=='\n' || (a)=='\r' || (a)=='\t')
|
|
||||||
|
|
||||||
/* The atoi macros assume that the buffer has only valid digits. */
|
|
||||||
#define atoi_1(p) (*(p) - '0' )
|
|
||||||
#define atoi_2(p) ((atoi_1(p) * 10) + atoi_1((p)+1))
|
|
||||||
#define atoi_4(p) ((atoi_2(p) * 100) + atoi_2((p)+2))
|
|
||||||
#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
|
|
||||||
*(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
|
|
||||||
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
|
|
||||||
#define xtoi_4(p) ((xtoi_2(p) * 256) + xtoi_2((p)+2))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*GNUPG_COMMON_UTIL_H*/
|
|
@ -1,169 +0,0 @@
|
|||||||
/* Like vsprintf but provides a pointer to malloc'd storage, which must
|
|
||||||
be freed by the caller.
|
|
||||||
Copyright (C) 1994, 2002 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of the libiberty library.
|
|
||||||
Libiberty is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Library General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Libiberty 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
|
|
||||||
Library General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
|
||||||
License along with libiberty; see the file COPYING.LIB. If
|
|
||||||
not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
Boston, MA 02111-1307, USA. */
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
#ifdef TEST
|
|
||||||
int global_total_width;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int
|
|
||||||
vasprintf (char **result, const char *format, va_list args)
|
|
||||||
{
|
|
||||||
const char *p = format;
|
|
||||||
/* Add one to make sure that it is never zero, which might cause malloc
|
|
||||||
to return NULL. */
|
|
||||||
int total_width = strlen (format) + 1;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
#ifdef va_copy
|
|
||||||
va_copy (ap, args);
|
|
||||||
#else
|
|
||||||
#ifdef __va_copy
|
|
||||||
__va_copy (ap, args);
|
|
||||||
#else
|
|
||||||
memcpy (&ap, args, sizeof (va_list));
|
|
||||||
#endif /* __va_copy */
|
|
||||||
#endif /* va_copy */
|
|
||||||
|
|
||||||
while (*p != '\0')
|
|
||||||
{
|
|
||||||
if (*p++ == '%')
|
|
||||||
{
|
|
||||||
while (strchr ("-+ #0", *p))
|
|
||||||
++p;
|
|
||||||
if (*p == '*')
|
|
||||||
{
|
|
||||||
++p;
|
|
||||||
total_width += abs (va_arg (ap, int));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
total_width += strtoul (p, (char**)&p, 10);
|
|
||||||
if (*p == '.')
|
|
||||||
{
|
|
||||||
++p;
|
|
||||||
if (*p == '*')
|
|
||||||
{
|
|
||||||
++p;
|
|
||||||
total_width += abs (va_arg (ap, int));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
total_width += strtoul (p, (char**)&p, 10);
|
|
||||||
}
|
|
||||||
while (strchr ("hlL", *p))
|
|
||||||
++p;
|
|
||||||
/* Should be big enough for any format specifier except %s
|
|
||||||
and floats. */
|
|
||||||
total_width += 30;
|
|
||||||
switch (*p)
|
|
||||||
{
|
|
||||||
case 'd':
|
|
||||||
case 'i':
|
|
||||||
case 'o':
|
|
||||||
case 'u':
|
|
||||||
case 'x':
|
|
||||||
case 'X':
|
|
||||||
case 'c':
|
|
||||||
(void) va_arg (ap, int);
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
case 'e':
|
|
||||||
case 'E':
|
|
||||||
case 'g':
|
|
||||||
case 'G':
|
|
||||||
(void) va_arg (ap, double);
|
|
||||||
/* Since an ieee double can have an exponent of 307, we'll
|
|
||||||
make the buffer wide enough to cover the gross case. */
|
|
||||||
total_width += 307;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
{
|
|
||||||
char *tmp = va_arg (ap, char *);
|
|
||||||
if (tmp)
|
|
||||||
total_width += strlen (tmp);
|
|
||||||
else /* in case the vsprintf does prints a text */
|
|
||||||
total_width += 25; /* e.g. "(null pointer reference)" */
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
case 'n':
|
|
||||||
(void) va_arg (ap, char *);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef TEST
|
|
||||||
global_total_width = total_width;
|
|
||||||
#endif
|
|
||||||
*result = malloc (total_width);
|
|
||||||
if (*result != NULL)
|
|
||||||
return vsprintf (*result, format, args);
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
asprintf (char **buf, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start (ap, fmt);
|
|
||||||
status = vasprintf (buf, fmt, ap);
|
|
||||||
va_end (ap);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef TEST
|
|
||||||
void
|
|
||||||
checkit (const char* format, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
char *result;
|
|
||||||
|
|
||||||
va_start (args, format);
|
|
||||||
vasprintf (&result, format, args);
|
|
||||||
if (strlen (result) < global_total_width)
|
|
||||||
printf ("PASS: ");
|
|
||||||
else
|
|
||||||
printf ("FAIL: ");
|
|
||||||
printf ("%d %s\n", global_total_width, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main (void)
|
|
||||||
{
|
|
||||||
checkit ("%d", 0x12345678);
|
|
||||||
checkit ("%200d", 5);
|
|
||||||
checkit ("%.300d", 6);
|
|
||||||
checkit ("%100.150d", 7);
|
|
||||||
checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
|
|
||||||
777777777777777777333333333333366666666666622222222222777777777777733333");
|
|
||||||
checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
|
|
||||||
}
|
|
||||||
#endif /* TEST */
|
|
@ -1,44 +0,0 @@
|
|||||||
/* xasprintf.c
|
|
||||||
* Copyright (C) 2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
#include "iobuf.h"
|
|
||||||
|
|
||||||
/* Same as asprintf but return an allocated buffer suitable to be
|
|
||||||
freed using xfree. This function simply dies on memory failure,
|
|
||||||
thus no extra check is required. */
|
|
||||||
char *
|
|
||||||
xasprintf (const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
char *buf, *p;
|
|
||||||
|
|
||||||
va_start (ap, fmt);
|
|
||||||
if (vasprintf (&buf, fmt, ap) < 0)
|
|
||||||
log_fatal ("asprintf failed: %s\n", strerror (errno));
|
|
||||||
va_end (ap);
|
|
||||||
p = xstrdup (buf);
|
|
||||||
free (buf);
|
|
||||||
return p;
|
|
||||||
}
|
|
@ -1,116 +0,0 @@
|
|||||||
/* xreadline.c - fgets replacement function
|
|
||||||
* Copyright (C) 1999, 2004 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* Same as fgets() but if the provided buffer is too short a larger
|
|
||||||
one will be allocated. This is similar to getline. A line is
|
|
||||||
considered a byte stream ending in a LF.
|
|
||||||
|
|
||||||
If MAX_LENGTH is not NULL, it shall point to a value with the
|
|
||||||
maximum allowed allocation.
|
|
||||||
|
|
||||||
Returns the length of the line. EOF is indicated by a line of
|
|
||||||
length zero. A truncated line is indicated my setting the value at
|
|
||||||
MAX_LENGTH to 0. If the returned value is less then 0 not enough
|
|
||||||
memory was enable and ERRNO is set accordingly.
|
|
||||||
|
|
||||||
If a line has been truncated, the file pointer is moved forward to
|
|
||||||
the end of the line so that the next read start with tghe next
|
|
||||||
line. Note that MAX_LENGTH must be re-initialzied in this case..
|
|
||||||
|
|
||||||
Note: The returned buffer is allocated with enough extra space to
|
|
||||||
append a CR,LF,Nul
|
|
||||||
*/
|
|
||||||
ssize_t
|
|
||||||
read_line (FILE *fp,
|
|
||||||
char **addr_of_buffer, size_t *length_of_buffer,
|
|
||||||
size_t *max_length)
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
char *buffer = *addr_of_buffer;
|
|
||||||
size_t length = *length_of_buffer;
|
|
||||||
size_t nbytes = 0;
|
|
||||||
size_t maxlen = max_length? *max_length : 0;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
if (!buffer)
|
|
||||||
{ /* No buffer given - allocate a new one. */
|
|
||||||
length = 256;
|
|
||||||
buffer = xtrymalloc (length);
|
|
||||||
*addr_of_buffer = buffer;
|
|
||||||
if (!buffer)
|
|
||||||
{
|
|
||||||
*length_of_buffer = 0;
|
|
||||||
if (max_length)
|
|
||||||
*max_length = 0;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*length_of_buffer = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
length -= 3; /* Reserve 3 bytes for CR,LF,EOL. */
|
|
||||||
p = buffer;
|
|
||||||
while ((c = getc (fp)) != EOF)
|
|
||||||
{
|
|
||||||
if (nbytes == length)
|
|
||||||
{ /* Enlarge the buffer. */
|
|
||||||
if (maxlen && length > maxlen) /* But not beyond our limit. */
|
|
||||||
{
|
|
||||||
/* Skip the rest of the line. */
|
|
||||||
while (c != '\n' && (c=getc (fp)) != EOF)
|
|
||||||
;
|
|
||||||
*p++ = '\n'; /* Always append a LF (we reserved some space). */
|
|
||||||
nbytes++;
|
|
||||||
if (max_length)
|
|
||||||
*max_length = 0; /* Indicate truncation. */
|
|
||||||
break; /* the while loop. */
|
|
||||||
}
|
|
||||||
length += 3; /* Adjust for the reserved bytes. */
|
|
||||||
length += length < 1024? 256 : 1024;
|
|
||||||
*addr_of_buffer = xtryrealloc (buffer, length);
|
|
||||||
if (!*addr_of_buffer)
|
|
||||||
{
|
|
||||||
int save_errno = errno;
|
|
||||||
xfree (buffer);
|
|
||||||
*length_of_buffer = *max_length = 0;
|
|
||||||
errno = save_errno;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
buffer = *addr_of_buffer;
|
|
||||||
*length_of_buffer = length;
|
|
||||||
length -= 3;
|
|
||||||
p = buffer + nbytes;
|
|
||||||
}
|
|
||||||
*p++ = c;
|
|
||||||
nbytes++;
|
|
||||||
if (c == '\n')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*p = 0; /* Make sure the line is a string. */
|
|
||||||
|
|
||||||
return nbytes;
|
|
||||||
}
|
|
@ -1,96 +0,0 @@
|
|||||||
/* yesno.c - Yes/No questions
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "i18n.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
int
|
|
||||||
answer_is_yes_no_default( const char *s, int def_answer )
|
|
||||||
{
|
|
||||||
const char *long_yes = _("yes");
|
|
||||||
const char *short_yes = _("yY");
|
|
||||||
const char *long_no = _("no");
|
|
||||||
const char *short_no = _("nN");
|
|
||||||
|
|
||||||
/* Note: we have to use the local dependent strcasecmp here */
|
|
||||||
if( !strcasecmp(s, long_yes ) )
|
|
||||||
return 1;
|
|
||||||
if( *s && strchr( short_yes, *s ) && !s[1] )
|
|
||||||
return 1;
|
|
||||||
/* test for no strings to catch ambiguities for the next test */
|
|
||||||
if( !strcasecmp(s, long_no ) )
|
|
||||||
return 0;
|
|
||||||
if( *s && strchr( short_no, *s ) && !s[1] )
|
|
||||||
return 0;
|
|
||||||
/* test for the english version (for those who are used to type yes) */
|
|
||||||
if( !ascii_strcasecmp(s, "yes" ) )
|
|
||||||
return 1;
|
|
||||||
if( *s && strchr( "yY", *s ) && !s[1] )
|
|
||||||
return 1;
|
|
||||||
return def_answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
answer_is_yes( const char *s )
|
|
||||||
{
|
|
||||||
return answer_is_yes_no_default(s,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Return 1 for yes, -1 for quit, or 0 for no
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
answer_is_yes_no_quit( const char *s )
|
|
||||||
{
|
|
||||||
const char *long_yes = _("yes");
|
|
||||||
const char *long_no = _("no");
|
|
||||||
const char *long_quit = _("quit");
|
|
||||||
const char *short_yes = _("yY");
|
|
||||||
const char *short_no = _("nN");
|
|
||||||
const char *short_quit = _("qQ");
|
|
||||||
|
|
||||||
/* Note: We have to use the locale dependent strcasecmp */
|
|
||||||
if( !strcasecmp(s, long_no ) )
|
|
||||||
return 0;
|
|
||||||
if( !strcasecmp(s, long_yes ) )
|
|
||||||
return 1;
|
|
||||||
if( !strcasecmp(s, long_quit ) )
|
|
||||||
return -1;
|
|
||||||
if( *s && strchr( short_no, *s ) && !s[1] )
|
|
||||||
return 0;
|
|
||||||
if( *s && strchr( short_yes, *s ) && !s[1] )
|
|
||||||
return 1;
|
|
||||||
if( *s && strchr( short_quit, *s ) && !s[1] )
|
|
||||||
return -1;
|
|
||||||
/* but not here */
|
|
||||||
if( !ascii_strcasecmp(s, "yes" ) )
|
|
||||||
return 1;
|
|
||||||
if( !ascii_strcasecmp(s, "quit" ) )
|
|
||||||
return -1;
|
|
||||||
if( *s && strchr( "yY", *s ) && !s[1] )
|
|
||||||
return 1;
|
|
||||||
if( *s && strchr( "qQ", *s ) && !s[1] )
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
1123
configure.ac
1123
configure.ac
File diff suppressed because it is too large
Load Diff
102
doc/ChangeLog
102
doc/ChangeLog
@ -1,102 +0,0 @@
|
|||||||
2004-06-18 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* debugging.texi: New.
|
|
||||||
* gnupg.texi: Include it.
|
|
||||||
|
|
||||||
2004-05-11 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gpgsm.texi (Esoteric Options): Add --debug-allow-core-dump.
|
|
||||||
|
|
||||||
2004-05-03 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gpg-agent.texi (Agent Options): Add --allow-mark-trusted.
|
|
||||||
|
|
||||||
2004-02-03 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* contrib.texi (Contributors): Updated from the gpg 1.2.3 thanks
|
|
||||||
list.
|
|
||||||
* gpgsm.texi, gpg-agent.texi, scdaemon.texi: Language cleanups.
|
|
||||||
|
|
||||||
2003-12-01 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gpgsm.texi (Certificate Options): Add --{enable,disable}-ocsp.
|
|
||||||
|
|
||||||
2003-11-17 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* scdaemon.texi (Scdaemon Options): Added --allow-admin and
|
|
||||||
--deny-admin.
|
|
||||||
|
|
||||||
2003-10-27 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gpg-agent.texi (Agent GET_CONFIRMATION): New.
|
|
||||||
|
|
||||||
2002-12-04 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gpg-agent.texi (Agent Signals): New.
|
|
||||||
|
|
||||||
2002-12-03 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gpgsm.texi (Operational Commands): Add --passwd and
|
|
||||||
--call-protect-tool.
|
|
||||||
* gpg-agent.texi (Agent PASSWD): New
|
|
||||||
|
|
||||||
2002-11-13 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gpg-agent.texi (Invoking GPG-AGENT): Tell about GPG_TTY.
|
|
||||||
|
|
||||||
2002-11-12 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gpgsm.texi (Operational Commands): Add --call-dirmngr.
|
|
||||||
|
|
||||||
2002-09-25 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gpg-agent.texi (Agent Options): Add --keep-tty and --keep-display.
|
|
||||||
|
|
||||||
2002-09-12 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gpg-agent.texi (Invoking GPG-AGENT): Explained how to start only
|
|
||||||
one instance.
|
|
||||||
|
|
||||||
2002-08-28 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gpg-agent.texi (Agent Options): Explained more options.
|
|
||||||
* scdaemon.texi (Scdaemon Options): Ditto.
|
|
||||||
|
|
||||||
2002-08-09 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* Makefile.am (gnupg_TEXINFOS): Include contrib.texi.
|
|
||||||
|
|
||||||
2002-08-06 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gpgsm.texi: Added more options.
|
|
||||||
|
|
||||||
2002-07-26 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* assuan.texi: New.
|
|
||||||
* gpgsm.texi, scdaemon.texi, gpg-agent.texi: Documented the Assuan
|
|
||||||
protocol used.
|
|
||||||
|
|
||||||
2002-07-22 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gnupg.texi, scdaemon.texi, gpg-agent.texi: New.
|
|
||||||
* contrib.texi, gpl.texi, fdl.texi: New.
|
|
||||||
* gpgsm.texi: Made this an include file for gnupg.texi.
|
|
||||||
* Makefile.am: Build gnupg.info instead of gpgsm.info.
|
|
||||||
|
|
||||||
2002-06-04 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* gpgsm.texi (Invocation): Described the various debug flags.
|
|
||||||
|
|
||||||
2002-05-14 Werner Koch <wk@gnupg.org>
|
|
||||||
|
|
||||||
* Makefile.am, gpgsm.texi: New.
|
|
||||||
|
|
||||||
Copyright 2002 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is free software; as a special exception the author gives
|
|
||||||
unlimited permission to copy and/or distribute it, with or without
|
|
||||||
modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
This file is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
|
||||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
@ -1,28 +0,0 @@
|
|||||||
# Copyright (C) 2002 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
|
|
||||||
|
|
||||||
## Process this file with automake to produce Makefile.in
|
|
||||||
|
|
||||||
info_TEXINFOS = gnupg.texi
|
|
||||||
|
|
||||||
gnupg_TEXINFOS = \
|
|
||||||
gpgsm.texi gpg-agent.texi scdaemon.texi assuan.texi\
|
|
||||||
debugging.texi contrib.texi gpl.texi fdl.texi
|
|
||||||
|
|
||||||
DISTCLEANFILES = gnupg.tmp gnupg.ops
|
|
||||||
|
|
189
doc/assuan.texi
189
doc/assuan.texi
@ -1,189 +0,0 @@
|
|||||||
@c Copyright (C) 2002 Free Software Foundation, Inc.
|
|
||||||
@c This is part of the GnuPG manual.
|
|
||||||
@c For copying conditions, see the file gnupg.texi.
|
|
||||||
|
|
||||||
@node Assuan
|
|
||||||
@chapter Description of the Assuan protocol.
|
|
||||||
|
|
||||||
The architecture of the modular GnuPG system is based on a couple of
|
|
||||||
highly specialized modules which make up a network of client server
|
|
||||||
communication. A common framework for intermodule communication is
|
|
||||||
therefore needed and should be implemented in a library.
|
|
||||||
|
|
||||||
Goals:
|
|
||||||
|
|
||||||
@itemize @bullet
|
|
||||||
@item Common framework for module communication
|
|
||||||
@item Easy debugging
|
|
||||||
@item Easy module testing
|
|
||||||
@item Extendible
|
|
||||||
@item Optional authentication and encryption facility
|
|
||||||
@item Usable to access external hardware
|
|
||||||
@end itemize
|
|
||||||
|
|
||||||
|
|
||||||
Design criteria:
|
|
||||||
|
|
||||||
@itemize @bullet
|
|
||||||
@item Client Server with back channel
|
|
||||||
@item Use a mainly text based protocol
|
|
||||||
@item Escape certain control characters
|
|
||||||
@item Allow indefinite data length
|
|
||||||
@item Request confidentiality for parts of the communication
|
|
||||||
@item Dummy module should allow direct linking of client and server.
|
|
||||||
@item Inline data or descriptor passing for bulk data
|
|
||||||
@item No protection against DoS needed
|
|
||||||
@item Subliminal channels are not an issue
|
|
||||||
@end itemize
|
|
||||||
|
|
||||||
Implementation:
|
|
||||||
|
|
||||||
The implementation is line based with a maximum line size of 1000
|
|
||||||
octects. The default IPC mechanism are Unix Domain Sockets.
|
|
||||||
|
|
||||||
On a connect request the server responds either with an okay or an error
|
|
||||||
status. For authentication check the server may send an Inquiry
|
|
||||||
Response prior to the first Okay, it may also issue Status messages.
|
|
||||||
The server must check that the client is allowed to connect, this is
|
|
||||||
done by requesting the credentials for the peer and comparing them to
|
|
||||||
those of the server. This avoids attacks based on wrong socket
|
|
||||||
permissions.
|
|
||||||
|
|
||||||
It may choose to delay the first response in case of an error. The
|
|
||||||
server never closes the connection - however the lower protocol may do
|
|
||||||
so after some time of inactivity or when the connection is in an error
|
|
||||||
state.
|
|
||||||
|
|
||||||
All textual messages are assumed to be in UTF-8 unless otherwise noted.
|
|
||||||
|
|
||||||
|
|
||||||
Server responses:
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
@item OK [<arbitary debugging information>]
|
|
||||||
Request was successful.
|
|
||||||
|
|
||||||
@item ERR @var{errorcode} [<human readable error description>]
|
|
||||||
Request could not be fulfilled. The error codes are mostly application
|
|
||||||
specific except for a few common ones.
|
|
||||||
|
|
||||||
@item S @var{keyword} <status information depending on keyword>
|
|
||||||
Informational output by the server, still processing the request.
|
|
||||||
|
|
||||||
@item # <string>
|
|
||||||
Comment line issued only for debugging purposes. Totally ignored.
|
|
||||||
|
|
||||||
@item D <raw data>
|
|
||||||
Raw data returned to client. There must be exactly one space after the
|
|
||||||
'D'. The values for '%', CR and LF must be percent escaped; this is
|
|
||||||
encoded as %25, %0D and %0A. Only uppercase letters should be used in
|
|
||||||
the hexadecimal representation. Other characters may be percent escaped
|
|
||||||
for easier debugging. All these Data lines are considered one data
|
|
||||||
stream up to the OK or ERR response. Status and Inquiry Responses
|
|
||||||
may be mixed with the Data lines.
|
|
||||||
|
|
||||||
@item INQUIRE @var{keyword}> <parameters>
|
|
||||||
Server needs further information from the client. The client should
|
|
||||||
answer with a command which is allowed after an inquiry. Note that the
|
|
||||||
server does not confirm that client command but either continues
|
|
||||||
processing or ends processing with an error status. Not all commands
|
|
||||||
are allowed.
|
|
||||||
@end table
|
|
||||||
|
|
||||||
|
|
||||||
A client should only check the first letter of each line and then skip
|
|
||||||
over to the next token (except for data lines where the raw data starts
|
|
||||||
exactly after 2 bytes). Lines larger than 1000 bytes should be
|
|
||||||
treated as a communication error. (The rationale for having a line
|
|
||||||
length limit is to allow for easier multiplexing of multiple channels).
|
|
||||||
|
|
||||||
|
|
||||||
Client requests:
|
|
||||||
|
|
||||||
The server waits for client requests after he sent an Okay or Error.
|
|
||||||
The client should not issue a request in other cases with the
|
|
||||||
exception of the CANCEL command.
|
|
||||||
|
|
||||||
@example
|
|
||||||
@var{command} <parameters>
|
|
||||||
@end example
|
|
||||||
|
|
||||||
@var{command} is a one word string without preceding white space.
|
|
||||||
Parameters are command specific, CR, LF and the percent signs should be
|
|
||||||
percent escaped as described above. To send a backslash as the last
|
|
||||||
character it should also be percent escaped. Percent escaping is
|
|
||||||
allowed anywhere in the parameters but not in the command. The line
|
|
||||||
ends with a CR, LF or just a LF.
|
|
||||||
|
|
||||||
Not yet implemented feature: If there is a need for a parameter list
|
|
||||||
longer than the line length limit (1000 characters including command and
|
|
||||||
CR, LF), the last character of the line (right before the CR/LF or LF)
|
|
||||||
must be a non-escape encoded backslash. The following line is then
|
|
||||||
expected to be a continuation of the line with the backslash replaced by
|
|
||||||
a blank and the line ending removed.
|
|
||||||
|
|
||||||
@example
|
|
||||||
D <raw data>
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Raw data to the server. There must be exactly one space after the 'D'.
|
|
||||||
The values for '%', CR and LF must be percent escaped; this is encoded
|
|
||||||
as %25, %0D and %0A. Only uppercase letters should be used in the
|
|
||||||
hexadecimal representation. Other characters may be percent escaped for
|
|
||||||
easier debugging. All these Data lines are considered one data stream
|
|
||||||
up to the OKAY or ERROR response. Status and Inquiry Responses may be
|
|
||||||
mixed with the Data lines.
|
|
||||||
|
|
||||||
@example
|
|
||||||
END
|
|
||||||
@end example
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Lines beginning with a @code{#} or empty lines are ignored. This is
|
|
||||||
useful to comment test scripts.
|
|
||||||
|
|
||||||
|
|
||||||
Although the commands are application specific, some of them are used by
|
|
||||||
all protocols and partly directly supported by the Assuan library:
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
@item CANCEL
|
|
||||||
his is the one special command which aborts the current request. it can
|
|
||||||
be sent at any time and the server will stop its operation right before
|
|
||||||
it would send the next response line (of any type).
|
|
||||||
|
|
||||||
@item BYE
|
|
||||||
Close the connect, the server will reply with an @code{OK}.
|
|
||||||
|
|
||||||
@item AUTH
|
|
||||||
Not yet specified as we don't implement it in the first phase. See my
|
|
||||||
mail to gpa-dev on 2001-10-25 about the rationale for measurements
|
|
||||||
against local attacks.
|
|
||||||
|
|
||||||
@item RESET
|
|
||||||
Reset the connection but not any existing authentication. The server
|
|
||||||
should release all resources associated with the connection.
|
|
||||||
|
|
||||||
@item END
|
|
||||||
Used by a client to mark the end of raw data. The server may send END
|
|
||||||
to indicate a partial end of data.
|
|
||||||
@end table
|
|
||||||
|
|
||||||
|
|
||||||
Error Codes:
|
|
||||||
|
|
||||||
Here we keep a list of error codes used in any Assuan based
|
|
||||||
protocol. The format is the string @code{ERR}, white space, the error
|
|
||||||
number, white space, a textual description of the error.
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
|
|
||||||
@item 100 Unknown Command
|
|
||||||
@item 101 Not Implemented
|
|
||||||
|
|
||||||
@item 301 certificate has been revoked [DirMngr]
|
|
||||||
@item 302 no CRL known for this certificate [DirMngr]
|
|
||||||
@item 303 CRL is too old and a new one could not be retrieved [DirMngr]
|
|
||||||
|
|
||||||
@end table
|
|
124
doc/contrib.texi
124
doc/contrib.texi
@ -1,124 +0,0 @@
|
|||||||
@c Copyright (C) 2002 Free Software Foundation, Inc.
|
|
||||||
@c This is part of the GnuPG manual.
|
|
||||||
@c For copying conditions, see the file gnupg.texi.
|
|
||||||
|
|
||||||
@node Contributors
|
|
||||||
@unnumbered Contributors to GnuPG
|
|
||||||
@cindex contributors
|
|
||||||
|
|
||||||
The GnuPG project would like to thank its many contributors. Without
|
|
||||||
them the project would not have been nearly as successful as it has
|
|
||||||
been. Any omissions in this list are accidental. Feel free to contact
|
|
||||||
the maintainer if you have been left out or some of your contributions
|
|
||||||
are not listed. Please keep this list in alphabetical order.
|
|
||||||
|
|
||||||
@itemize @bullet
|
|
||||||
|
|
||||||
@item
|
|
||||||
Bernhard Herzog did extensive testing and tracked down a lot of bugs
|
|
||||||
|
|
||||||
@item
|
|
||||||
Bernhard Reiter made sure that we met the specifications and the
|
|
||||||
deadlines. He did extensive testing and came up with a lot of suggestions.
|
|
||||||
|
|
||||||
@item
|
|
||||||
Jan-Oliver Wagner made sure that we met the specifications and the
|
|
||||||
deadlines. He did extensive testing and came up with a lot of suggestions.
|
|
||||||
|
|
||||||
@item
|
|
||||||
Karl-Heinz Zimmer had to struggle with all the bugs and misconceptions
|
|
||||||
while working on Kmail integration.
|
|
||||||
|
|
||||||
@item
|
|
||||||
Marcus Brinkman cleaned up the Assuan code and fixed bugs all over the place.
|
|
||||||
|
|
||||||
@item
|
|
||||||
Steffen Hansen had a hard time to write the dirmngr due to
|
|
||||||
underspecified interfaces.
|
|
||||||
|
|
||||||
@item
|
|
||||||
Thomas Koester did extensive testing and tracked down a lot of bugs
|
|
||||||
|
|
||||||
@item
|
|
||||||
Werner Koch designed the system and wrote most of the original code.
|
|
||||||
|
|
||||||
@end itemize
|
|
||||||
|
|
||||||
We'd also like to thank these folks who have contributed a lot of time
|
|
||||||
and energy working on GnuPG over the years:
|
|
||||||
|
|
||||||
David Shaw, Matthew Skala, Michael Roth, Niklas Hernaeus, Nils
|
|
||||||
Ellmenreich, Rémi Guyomarch, Stefan Bellon, Timo Schulz and Werner
|
|
||||||
Koch wrote the code. Birger Langkjer, Daniel Resare, Dokianakis
|
|
||||||
Theofanis, Edmund GRIMLEY EVANS, Gaël Quéri, Gregory Steuck, Nagy
|
|
||||||
Ferenc László, Ivo Timmermans, Jacobo Tarri'o Barreiro, Janusz
|
|
||||||
Aleksander Urbanowicz, Jedi Lin, Jouni Hiltunen, Laurentiu Buzdugan,
|
|
||||||
Magda Procha'zkova', Michael Anckaert, Michal Majer, Marco d'Itri,
|
|
||||||
Nilgun Belma Buguner, Pedro Morais, Tedi Heriyanto, Thiago Jung
|
|
||||||
Bauermann, Rafael Caetano dos Santos, Toomas Soome, Urko Lusa, Walter
|
|
||||||
Koch, Yosiaki IIDA did the official translations. Mike Ashley wrote
|
|
||||||
and maintains the GNU Privacy Handbook. David Scribner is the current
|
|
||||||
FAQ editor. Lorenzo Cappelletti maintains the web site.
|
|
||||||
|
|
||||||
The following people helped greatly by suggesting improvements,
|
|
||||||
testing, fixing bugs, providing resources and doing other important
|
|
||||||
tasks: Adam Mitchell, Albert Chin, Alec Habig, Allan Clark, Anand
|
|
||||||
Kumria, Andreas Haumer, Anthony Mulcahy, Ariel T Glenn, Bob Mathews,
|
|
||||||
Bodo Moeller, Brendan O'Dea, Brenno de Winter, Brian M. Carlson, Brian
|
|
||||||
Moore, Brian Warner, Bryan Fullerton, Caskey L. Dickson, Cees van de
|
|
||||||
Griend, Charles Levert, Chip Salzenberg, Chris Adams, Christian Biere,
|
|
||||||
Christian Kurz, Christian von Roques, Christopher Oliver, Christian
|
|
||||||
Recktenwald, Dan Winship, Daniel Eisenbud, Daniel Koening, Dave
|
|
||||||
Dykstra, David C Niemi, David Champion, David Ellement, David
|
|
||||||
Hallinan, David Hollenberg, David Mathog, David R. Bergstein, Detlef
|
|
||||||
Lannert, Dimitri, Dirk Lattermann, Dirk Meyer, Disastry, Douglas
|
|
||||||
Calvert, Ed Boraas, Edmund GRIMLEY EVANS, Edwin Woudt, Enzo
|
|
||||||
Michelangeli, Ernst Molitor, Fabio Coatti, Felix von Leitner, fish
|
|
||||||
stiqz, Florian Weimer, Francesco Potorti, Frank Donahoe, Frank
|
|
||||||
Heckenbach, Frank Stajano, Frank Tobin, Gabriel Rosenkoetter, Gaël
|
|
||||||
Quéri, Gene Carter, Geoff Keating, Georg Schwarz, Giampaolo Tomassoni,
|
|
||||||
Gilbert Fernandes, Greg Louis, Greg Troxel, Gregory Steuck, Gregery
|
|
||||||
Barton, Harald Denker, Holger Baust, Hendrik Buschkamp, Holger
|
|
||||||
Schurig, Holger Smolinski, Holger Trapp, Hugh Daniel, Huy Le, Ian
|
|
||||||
McKellar, Ivo Timmermans, Jan Krueger, Jan Niehusmann, Janusz
|
|
||||||
A. Urbanowicz, James Troup, Jean-loup Gailly, Jeff Long, Jeffery Von
|
|
||||||
Ronne, Jens Bachem, Jeroen C. van Gelderen, J Horacio MG, J. Michael
|
|
||||||
Ashley, Jim Bauer, Jim Small, Joachim Backes, Joe Rhett, John
|
|
||||||
A. Martin, Johnny Teveßen, Jörg Schilling, Jos Backus, Joseph Walton,
|
|
||||||
Juan F. Codagnone, Jun Kuriyama, Kahil D. Jallad, Karl Fogel, Karsten
|
|
||||||
Thygesen, Katsuhiro Kondou, Kazu Yamamoto, Keith Clayton, Kevin Ryde,
|
|
||||||
Klaus Singvogel, Kurt Garloff, Lars Kellogg-Stedman, L. Sassaman, M
|
|
||||||
Taylor, Marcel Waldvogel, Marco d'Itri, Marco Parrone, Marcus
|
|
||||||
Brinkmann, Mark Adler, Mark Elbrecht, Mark Pettit, Markus Friedl,
|
|
||||||
Martin Kahlert, Martin Hamilton, Martin Schulte, Matt Kraai, Matthew
|
|
||||||
Skala, Matthew Wilcox, Matthias Urlichs, Max Valianskiy, Michael
|
|
||||||
Engels, Michael Fischer v. Mollard, Michael Roth, Michael Sobolev,
|
|
||||||
Michael Tokarev, Nicolas Graner, Mike McEwan, Neal H Walfield, Nelson
|
|
||||||
H. F. Beebe, NIIBE Yutaka, Niklas Hernaeus, Nimrod Zimerman, N J Doye,
|
|
||||||
Oliver Haakert, Oskari Jääskeläinen, Pascal Scheffers, Paul D. Smith,
|
|
||||||
Per Cederqvist, Phil Blundell, Philippe Laliberte, Peter Fales, Peter
|
|
||||||
Gutmann, Peter Marschall, Peter Valchev, Piotr Krukowiecki, QingLong,
|
|
||||||
Ralph Gillen, Rat, Reinhard Wobst, Rémi Guyomarch, Reuben Sumner,
|
|
||||||
Richard Outerbridge, Robert Joop, Roddy Strachan, Roger Sondermann,
|
|
||||||
Roland Rosenfeld, Roman Pavlik, Ross Golder, Ryan Malayter, Sam
|
|
||||||
Roberts, Sami Tolvanen, Sean MacLennan, Sebastian Klemke, Serge
|
|
||||||
Munhoven, SL Baur, Stefan Bellon, Dr.Stefan.Dalibor, Stefan Karrmann,
|
|
||||||
Stefan Keller, Steffen Ullrich, Steffen Zahn, Steven Bakker, Steven
|
|
||||||
Murdoch, Susanne Schultz, Ted Cabeen, Thiago Jung Bauermann, Thijmen
|
|
||||||
Klok, Thomas Roessler, Tim Mooney, Timo Schulz, Todd Vierling, TOGAWA
|
|
||||||
Satoshi, Tom Spindler, Tom Zerucha, Tomas Fasth, Tommi Komulainen,
|
|
||||||
Thomas Klausner, Tomasz Kozlowski, Thomas Mikkelsen, Ulf Möller, Urko
|
|
||||||
Lusa, Vincent P. Broman, Volker Quetschke, W Lewis, Walter Hofmann,
|
|
||||||
Walter Koch, Wayne Chapeskie, Wim Vandeputte, Winona Brown, Yosiaki
|
|
||||||
IIDA, Yoshihiro Kajiki and Gerlinde Klaes.
|
|
||||||
|
|
||||||
This software has been made possible by the previous work of Chris
|
|
||||||
Wedgwood, Jean-loup Gailly, Jon Callas, Mark Adler, Martin Hellmann
|
|
||||||
Paul Kendall, Philip R. Zimmermann, Peter Gutmann, Philip A. Nelson,
|
|
||||||
Taher ElGamal, Torbjorn Granlund, Whitfield Diffie, some unknown NSA
|
|
||||||
mathematicians and all the folks who have worked hard to create
|
|
||||||
complete and free operating systems.
|
|
||||||
|
|
||||||
And finally we'd like to thank everyone who uses these tools, submits
|
|
||||||
bug reports and generally reminds us why we're doing this work in the
|
|
||||||
first place.
|
|
@ -1,82 +0,0 @@
|
|||||||
@c Copyright (C) 2004 Free Software Foundation, Inc.
|
|
||||||
@c This is part of the GnuPG manual.
|
|
||||||
@c For copying conditions, see the file gnupg.texi.
|
|
||||||
|
|
||||||
@node Debugging
|
|
||||||
@chapter How to solve problems
|
|
||||||
|
|
||||||
Everone knows that software often does not do what it should do and thus
|
|
||||||
there is a need to track down problems. We call this debugging in a
|
|
||||||
reminiscent to the moth jamming a relay in a Mark II box back in 1947.
|
|
||||||
|
|
||||||
Most of the probelsm a merely configuration and user problems but
|
|
||||||
nevertheless there are the most annoying ones and reposnible for may
|
|
||||||
gray hairs. We try to give some guidelines here on how to identify and
|
|
||||||
solve the problem at hand.
|
|
||||||
|
|
||||||
|
|
||||||
@menu
|
|
||||||
* Debugging Tools:: Description of some useful tools
|
|
||||||
|
|
||||||
@end menu
|
|
||||||
|
|
||||||
|
|
||||||
@node Debugging Tools
|
|
||||||
@section Debugging Tools
|
|
||||||
|
|
||||||
The GnuPG distribution comes with a couple of tools, useful to help find
|
|
||||||
and solving problems.
|
|
||||||
|
|
||||||
@menu
|
|
||||||
* kbxutil:: Scrutinizing a keybox file.
|
|
||||||
@end menu
|
|
||||||
|
|
||||||
@node kbxutil
|
|
||||||
@subsection Scrutinizing a keybox file
|
|
||||||
|
|
||||||
A keybox is a file fomat used to store public keys along with meta
|
|
||||||
information and indices. The commonly used one is the file
|
|
||||||
@file{pubring.kbx} in the @file{.gnupg} directory. It contains all
|
|
||||||
X.509 certificates as well as OpenPGP keys@footnote{Well, OpenPGP keys
|
|
||||||
are not implemented, @command{gpg} still used the keyring file
|
|
||||||
@file{pubring.gpg}} .
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
When called the standard way, e.g.:
|
|
||||||
|
|
||||||
@samp{kbxutil ~/.gnupg/pubring.kbx}
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
it lists all records (called @acronym{blobs}) with there meta-information
|
|
||||||
in a human readable format.
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
To see statistics on the keybox in question, run it using
|
|
||||||
|
|
||||||
@samp{kbxutil --stats ~/.gnupg/pubring.kbx}
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
and you get an output like:
|
|
||||||
|
|
||||||
@example
|
|
||||||
Total number of blobs: 99
|
|
||||||
header: 1
|
|
||||||
empty: 0
|
|
||||||
openpgp: 0
|
|
||||||
x509: 98
|
|
||||||
non flagged: 81
|
|
||||||
secret flagged: 0
|
|
||||||
ephemeral flagged: 17
|
|
||||||
@end example
|
|
||||||
|
|
||||||
In this example you see that the keybox does not have any OpenPGP keys
|
|
||||||
but contains 98 X.509 cerificates and a total of 17 keys or certificates
|
|
||||||
are flagges as ephemeral, meaning that they are only temporary stored
|
|
||||||
(cached) in the keybox and won't get listed using the usual commands
|
|
||||||
provided by @command{gpgsm} or @command{gpg}. 81 certifcates are stored
|
|
||||||
in a standard way and directly available from @command{gpgsm}.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
401
doc/fdl.texi
401
doc/fdl.texi
@ -1,401 +0,0 @@
|
|||||||
@node GNU Free Documentation License
|
|
||||||
@appendix GNU Free Documentation License
|
|
||||||
|
|
||||||
@cindex FDL, GNU Free Documentation License
|
|
||||||
@center Version 1.1, March 2000
|
|
||||||
|
|
||||||
@display
|
|
||||||
Copyright @copyright{} 2000 Free Software Foundation, Inc.
|
|
||||||
59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
|
|
||||||
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
@end display
|
|
||||||
|
|
||||||
@enumerate 0
|
|
||||||
@item
|
|
||||||
PREAMBLE
|
|
||||||
|
|
||||||
The purpose of this License is to make a manual, textbook, or other
|
|
||||||
written document @dfn{free} in the sense of freedom: to assure everyone
|
|
||||||
the effective freedom to copy and redistribute it, with or without
|
|
||||||
modifying it, either commercially or noncommercially. Secondarily,
|
|
||||||
this License preserves for the author and publisher a way to get
|
|
||||||
credit for their work, while not being considered responsible for
|
|
||||||
modifications made by others.
|
|
||||||
|
|
||||||
This License is a kind of ``copyleft'', which means that derivative
|
|
||||||
works of the document must themselves be free in the same sense. It
|
|
||||||
complements the GNU General Public License, which is a copyleft
|
|
||||||
license designed for free software.
|
|
||||||
|
|
||||||
We have designed this License in order to use it for manuals for free
|
|
||||||
software, because free software needs free documentation: a free
|
|
||||||
program should come with manuals providing the same freedoms that the
|
|
||||||
software does. But this License is not limited to software manuals;
|
|
||||||
it can be used for any textual work, regardless of subject matter or
|
|
||||||
whether it is published as a printed book. We recommend this License
|
|
||||||
principally for works whose purpose is instruction or reference.
|
|
||||||
|
|
||||||
@item
|
|
||||||
APPLICABILITY AND DEFINITIONS
|
|
||||||
|
|
||||||
This License applies to any manual or other work that contains a
|
|
||||||
notice placed by the copyright holder saying it can be distributed
|
|
||||||
under the terms of this License. The ``Document'', below, refers to any
|
|
||||||
such manual or work. Any member of the public is a licensee, and is
|
|
||||||
addressed as ``you''.
|
|
||||||
|
|
||||||
A ``Modified Version'' of the Document means any work containing the
|
|
||||||
Document or a portion of it, either copied verbatim, or with
|
|
||||||
modifications and/or translated into another language.
|
|
||||||
|
|
||||||
A ``Secondary Section'' is a named appendix or a front-matter section of
|
|
||||||
the Document that deals exclusively with the relationship of the
|
|
||||||
publishers or authors of the Document to the Document's overall subject
|
|
||||||
(or to related matters) and contains nothing that could fall directly
|
|
||||||
within that overall subject. (For example, if the Document is in part a
|
|
||||||
textbook of mathematics, a Secondary Section may not explain any
|
|
||||||
mathematics.) The relationship could be a matter of historical
|
|
||||||
connection with the subject or with related matters, or of legal,
|
|
||||||
commercial, philosophical, ethical or political position regarding
|
|
||||||
them.
|
|
||||||
|
|
||||||
The ``Invariant Sections'' are certain Secondary Sections whose titles
|
|
||||||
are designated, as being those of Invariant Sections, in the notice
|
|
||||||
that says that the Document is released under this License.
|
|
||||||
|
|
||||||
The ``Cover Texts'' are certain short passages of text that are listed,
|
|
||||||
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
|
|
||||||
the Document is released under this License.
|
|
||||||
|
|
||||||
A ``Transparent'' copy of the Document means a machine-readable copy,
|
|
||||||
represented in a format whose specification is available to the
|
|
||||||
general public, whose contents can be viewed and edited directly and
|
|
||||||
straightforwardly with generic text editors or (for images composed of
|
|
||||||
pixels) generic paint programs or (for drawings) some widely available
|
|
||||||
drawing editor, and that is suitable for input to text formatters or
|
|
||||||
for automatic translation to a variety of formats suitable for input
|
|
||||||
to text formatters. A copy made in an otherwise Transparent file
|
|
||||||
format whose markup has been designed to thwart or discourage
|
|
||||||
subsequent modification by readers is not Transparent. A copy that is
|
|
||||||
not ``Transparent'' is called ``Opaque''.
|
|
||||||
|
|
||||||
Examples of suitable formats for Transparent copies include plain
|
|
||||||
@sc{ascii} without markup, Texinfo input format, La@TeX{} input format,
|
|
||||||
@acronym{SGML} or @acronym{XML} using a publicly available
|
|
||||||
@acronym{DTD}, and standard-conforming simple @acronym{HTML} designed
|
|
||||||
for human modification. Opaque formats include PostScript,
|
|
||||||
@acronym{PDF}, proprietary formats that can be read and edited only by
|
|
||||||
proprietary word processors, @acronym{SGML} or @acronym{XML} for which
|
|
||||||
the @acronym{DTD} and/or processing tools are not generally available,
|
|
||||||
and the machine-generated @acronym{HTML} produced by some word
|
|
||||||
processors for output purposes only.
|
|
||||||
|
|
||||||
The ``Title Page'' means, for a printed book, the title page itself,
|
|
||||||
plus such following pages as are needed to hold, legibly, the material
|
|
||||||
this License requires to appear in the title page. For works in
|
|
||||||
formats which do not have any title page as such, ``Title Page'' means
|
|
||||||
the text near the most prominent appearance of the work's title,
|
|
||||||
preceding the beginning of the body of the text.
|
|
||||||
|
|
||||||
@item
|
|
||||||
VERBATIM COPYING
|
|
||||||
|
|
||||||
You may copy and distribute the Document in any medium, either
|
|
||||||
commercially or noncommercially, provided that this License, the
|
|
||||||
copyright notices, and the license notice saying this License applies
|
|
||||||
to the Document are reproduced in all copies, and that you add no other
|
|
||||||
conditions whatsoever to those of this License. You may not use
|
|
||||||
technical measures to obstruct or control the reading or further
|
|
||||||
copying of the copies you make or distribute. However, you may accept
|
|
||||||
compensation in exchange for copies. If you distribute a large enough
|
|
||||||
number of copies you must also follow the conditions in section 3.
|
|
||||||
|
|
||||||
You may also lend copies, under the same conditions stated above, and
|
|
||||||
you may publicly display copies.
|
|
||||||
|
|
||||||
@item
|
|
||||||
COPYING IN QUANTITY
|
|
||||||
|
|
||||||
If you publish printed copies of the Document numbering more than 100,
|
|
||||||
and the Document's license notice requires Cover Texts, you must enclose
|
|
||||||
the copies in covers that carry, clearly and legibly, all these Cover
|
|
||||||
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
|
|
||||||
the back cover. Both covers must also clearly and legibly identify
|
|
||||||
you as the publisher of these copies. The front cover must present
|
|
||||||
the full title with all words of the title equally prominent and
|
|
||||||
visible. You may add other material on the covers in addition.
|
|
||||||
Copying with changes limited to the covers, as long as they preserve
|
|
||||||
the title of the Document and satisfy these conditions, can be treated
|
|
||||||
as verbatim copying in other respects.
|
|
||||||
|
|
||||||
If the required texts for either cover are too voluminous to fit
|
|
||||||
legibly, you should put the first ones listed (as many as fit
|
|
||||||
reasonably) on the actual cover, and continue the rest onto adjacent
|
|
||||||
pages.
|
|
||||||
|
|
||||||
If you publish or distribute Opaque copies of the Document numbering
|
|
||||||
more than 100, you must either include a machine-readable Transparent
|
|
||||||
copy along with each Opaque copy, or state in or with each Opaque copy
|
|
||||||
a publicly-accessible computer-network location containing a complete
|
|
||||||
Transparent copy of the Document, free of added material, which the
|
|
||||||
general network-using public has access to download anonymously at no
|
|
||||||
charge using public-standard network protocols. If you use the latter
|
|
||||||
option, you must take reasonably prudent steps, when you begin
|
|
||||||
distribution of Opaque copies in quantity, to ensure that this
|
|
||||||
Transparent copy will remain thus accessible at the stated location
|
|
||||||
until at least one year after the last time you distribute an Opaque
|
|
||||||
copy (directly or through your agents or retailers) of that edition to
|
|
||||||
the public.
|
|
||||||
|
|
||||||
It is requested, but not required, that you contact the authors of the
|
|
||||||
Document well before redistributing any large number of copies, to give
|
|
||||||
them a chance to provide you with an updated version of the Document.
|
|
||||||
|
|
||||||
@item
|
|
||||||
MODIFICATIONS
|
|
||||||
|
|
||||||
You may copy and distribute a Modified Version of the Document under
|
|
||||||
the conditions of sections 2 and 3 above, provided that you release
|
|
||||||
the Modified Version under precisely this License, with the Modified
|
|
||||||
Version filling the role of the Document, thus licensing distribution
|
|
||||||
and modification of the Modified Version to whoever possesses a copy
|
|
||||||
of it. In addition, you must do these things in the Modified Version:
|
|
||||||
|
|
||||||
@enumerate A
|
|
||||||
@item
|
|
||||||
Use in the Title Page (and on the covers, if any) a title distinct
|
|
||||||
from that of the Document, and from those of previous versions
|
|
||||||
(which should, if there were any, be listed in the History section
|
|
||||||
of the Document). You may use the same title as a previous version
|
|
||||||
if the original publisher of that version gives permission.
|
|
||||||
|
|
||||||
@item
|
|
||||||
List on the Title Page, as authors, one or more persons or entities
|
|
||||||
responsible for authorship of the modifications in the Modified
|
|
||||||
Version, together with at least five of the principal authors of the
|
|
||||||
Document (all of its principal authors, if it has less than five).
|
|
||||||
|
|
||||||
@item
|
|
||||||
State on the Title page the name of the publisher of the
|
|
||||||
Modified Version, as the publisher.
|
|
||||||
|
|
||||||
@item
|
|
||||||
Preserve all the copyright notices of the Document.
|
|
||||||
|
|
||||||
@item
|
|
||||||
Add an appropriate copyright notice for your modifications
|
|
||||||
adjacent to the other copyright notices.
|
|
||||||
|
|
||||||
@item
|
|
||||||
Include, immediately after the copyright notices, a license notice
|
|
||||||
giving the public permission to use the Modified Version under the
|
|
||||||
terms of this License, in the form shown in the Addendum below.
|
|
||||||
|
|
||||||
@item
|
|
||||||
Preserve in that license notice the full lists of Invariant Sections
|
|
||||||
and required Cover Texts given in the Document's license notice.
|
|
||||||
|
|
||||||
@item
|
|
||||||
Include an unaltered copy of this License.
|
|
||||||
|
|
||||||
@item
|
|
||||||
Preserve the section entitled ``History'', and its title, and add to
|
|
||||||
it an item stating at least the title, year, new authors, and
|
|
||||||
publisher of the Modified Version as given on the Title Page. If
|
|
||||||
there is no section entitled ``History'' in the Document, create one
|
|
||||||
stating the title, year, authors, and publisher of the Document as
|
|
||||||
given on its Title Page, then add an item describing the Modified
|
|
||||||
Version as stated in the previous sentence.
|
|
||||||
|
|
||||||
@item
|
|
||||||
Preserve the network location, if any, given in the Document for
|
|
||||||
public access to a Transparent copy of the Document, and likewise
|
|
||||||
the network locations given in the Document for previous versions
|
|
||||||
it was based on. These may be placed in the ``History'' section.
|
|
||||||
You may omit a network location for a work that was published at
|
|
||||||
least four years before the Document itself, or if the original
|
|
||||||
publisher of the version it refers to gives permission.
|
|
||||||
|
|
||||||
@item
|
|
||||||
In any section entitled ``Acknowledgments'' or ``Dedications'',
|
|
||||||
preserve the section's title, and preserve in the section all the
|
|
||||||
substance and tone of each of the contributor acknowledgments
|
|
||||||
and/or dedications given therein.
|
|
||||||
|
|
||||||
@item
|
|
||||||
Preserve all the Invariant Sections of the Document,
|
|
||||||
unaltered in their text and in their titles. Section numbers
|
|
||||||
or the equivalent are not considered part of the section titles.
|
|
||||||
|
|
||||||
@item
|
|
||||||
Delete any section entitled ``Endorsements''. Such a section
|
|
||||||
may not be included in the Modified Version.
|
|
||||||
|
|
||||||
@item
|
|
||||||
Do not retitle any existing section as ``Endorsements''
|
|
||||||
or to conflict in title with any Invariant Section.
|
|
||||||
@end enumerate
|
|
||||||
|
|
||||||
If the Modified Version includes new front-matter sections or
|
|
||||||
appendices that qualify as Secondary Sections and contain no material
|
|
||||||
copied from the Document, you may at your option designate some or all
|
|
||||||
of these sections as invariant. To do this, add their titles to the
|
|
||||||
list of Invariant Sections in the Modified Version's license notice.
|
|
||||||
These titles must be distinct from any other section titles.
|
|
||||||
|
|
||||||
You may add a section entitled ``Endorsements'', provided it contains
|
|
||||||
nothing but endorsements of your Modified Version by various
|
|
||||||
parties---for example, statements of peer review or that the text has
|
|
||||||
been approved by an organization as the authoritative definition of a
|
|
||||||
standard.
|
|
||||||
|
|
||||||
You may add a passage of up to five words as a Front-Cover Text, and a
|
|
||||||
passage of up to 25 words as a Back-Cover Text, to the end of the list
|
|
||||||
of Cover Texts in the Modified Version. Only one passage of
|
|
||||||
Front-Cover Text and one of Back-Cover Text may be added by (or
|
|
||||||
through arrangements made by) any one entity. If the Document already
|
|
||||||
includes a cover text for the same cover, previously added by you or
|
|
||||||
by arrangement made by the same entity you are acting on behalf of,
|
|
||||||
you may not add another; but you may replace the old one, on explicit
|
|
||||||
permission from the previous publisher that added the old one.
|
|
||||||
|
|
||||||
The author(s) and publisher(s) of the Document do not by this License
|
|
||||||
give permission to use their names for publicity for or to assert or
|
|
||||||
imply endorsement of any Modified Version.
|
|
||||||
|
|
||||||
@item
|
|
||||||
COMBINING DOCUMENTS
|
|
||||||
|
|
||||||
You may combine the Document with other documents released under this
|
|
||||||
License, under the terms defined in section 4 above for modified
|
|
||||||
versions, provided that you include in the combination all of the
|
|
||||||
Invariant Sections of all of the original documents, unmodified, and
|
|
||||||
list them all as Invariant Sections of your combined work in its
|
|
||||||
license notice.
|
|
||||||
|
|
||||||
The combined work need only contain one copy of this License, and
|
|
||||||
multiple identical Invariant Sections may be replaced with a single
|
|
||||||
copy. If there are multiple Invariant Sections with the same name but
|
|
||||||
different contents, make the title of each such section unique by
|
|
||||||
adding at the end of it, in parentheses, the name of the original
|
|
||||||
author or publisher of that section if known, or else a unique number.
|
|
||||||
Make the same adjustment to the section titles in the list of
|
|
||||||
Invariant Sections in the license notice of the combined work.
|
|
||||||
|
|
||||||
In the combination, you must combine any sections entitled ``History''
|
|
||||||
in the various original documents, forming one section entitled
|
|
||||||
``History''; likewise combine any sections entitled ``Acknowledgments'',
|
|
||||||
and any sections entitled ``Dedications''. You must delete all sections
|
|
||||||
entitled ``Endorsements.''
|
|
||||||
|
|
||||||
@item
|
|
||||||
COLLECTIONS OF DOCUMENTS
|
|
||||||
|
|
||||||
You may make a collection consisting of the Document and other documents
|
|
||||||
released under this License, and replace the individual copies of this
|
|
||||||
License in the various documents with a single copy that is included in
|
|
||||||
the collection, provided that you follow the rules of this License for
|
|
||||||
verbatim copying of each of the documents in all other respects.
|
|
||||||
|
|
||||||
You may extract a single document from such a collection, and distribute
|
|
||||||
it individually under this License, provided you insert a copy of this
|
|
||||||
License into the extracted document, and follow this License in all
|
|
||||||
other respects regarding verbatim copying of that document.
|
|
||||||
|
|
||||||
@item
|
|
||||||
AGGREGATION WITH INDEPENDENT WORKS
|
|
||||||
|
|
||||||
A compilation of the Document or its derivatives with other separate
|
|
||||||
and independent documents or works, in or on a volume of a storage or
|
|
||||||
distribution medium, does not as a whole count as a Modified Version
|
|
||||||
of the Document, provided no compilation copyright is claimed for the
|
|
||||||
compilation. Such a compilation is called an ``aggregate'', and this
|
|
||||||
License does not apply to the other self-contained works thus compiled
|
|
||||||
with the Document, on account of their being thus compiled, if they
|
|
||||||
are not themselves derivative works of the Document.
|
|
||||||
|
|
||||||
If the Cover Text requirement of section 3 is applicable to these
|
|
||||||
copies of the Document, then if the Document is less than one quarter
|
|
||||||
of the entire aggregate, the Document's Cover Texts may be placed on
|
|
||||||
covers that surround only the Document within the aggregate.
|
|
||||||
Otherwise they must appear on covers around the whole aggregate.
|
|
||||||
|
|
||||||
@item
|
|
||||||
TRANSLATION
|
|
||||||
|
|
||||||
Translation is considered a kind of modification, so you may
|
|
||||||
distribute translations of the Document under the terms of section 4.
|
|
||||||
Replacing Invariant Sections with translations requires special
|
|
||||||
permission from their copyright holders, but you may include
|
|
||||||
translations of some or all Invariant Sections in addition to the
|
|
||||||
original versions of these Invariant Sections. You may include a
|
|
||||||
translation of this License provided that you also include the
|
|
||||||
original English version of this License. In case of a disagreement
|
|
||||||
between the translation and the original English version of this
|
|
||||||
License, the original English version will prevail.
|
|
||||||
|
|
||||||
@item
|
|
||||||
TERMINATION
|
|
||||||
|
|
||||||
You may not copy, modify, sublicense, or distribute the Document except
|
|
||||||
as expressly provided for under this License. Any other attempt to
|
|
||||||
copy, modify, sublicense or distribute the Document is void, and will
|
|
||||||
automatically terminate your rights under this License. However,
|
|
||||||
parties who have received copies, or rights, from you under this
|
|
||||||
License will not have their licenses terminated so long as such
|
|
||||||
parties remain in full compliance.
|
|
||||||
|
|
||||||
@item
|
|
||||||
FUTURE REVISIONS OF THIS LICENSE
|
|
||||||
|
|
||||||
The Free Software Foundation may publish new, revised versions
|
|
||||||
of the GNU Free Documentation License from time to time. Such new
|
|
||||||
versions will be similar in spirit to the present version, but may
|
|
||||||
differ in detail to address new problems or concerns. See
|
|
||||||
@uref{http://www.gnu.org/copyleft/}.
|
|
||||||
|
|
||||||
Each version of the License is given a distinguishing version number.
|
|
||||||
If the Document specifies that a particular numbered version of this
|
|
||||||
License ``or any later version'' applies to it, you have the option of
|
|
||||||
following the terms and conditions either of that specified version or
|
|
||||||
of any later version that has been published (not as a draft) by the
|
|
||||||
Free Software Foundation. If the Document does not specify a version
|
|
||||||
number of this License, you may choose any version ever published (not
|
|
||||||
as a draft) by the Free Software Foundation.
|
|
||||||
@end enumerate
|
|
||||||
|
|
||||||
@page
|
|
||||||
@appendixsubsec ADDENDUM: How to use this License for your documents
|
|
||||||
|
|
||||||
To use this License in a document you have written, include a copy of
|
|
||||||
the License in the document and put the following copyright and
|
|
||||||
license notices just after the title page:
|
|
||||||
|
|
||||||
@smallexample
|
|
||||||
@group
|
|
||||||
Copyright (C) @var{year} @var{your name}.
|
|
||||||
Permission is granted to copy, distribute and/or modify this document
|
|
||||||
under the terms of the GNU Free Documentation License, Version 1.1
|
|
||||||
or any later version published by the Free Software Foundation;
|
|
||||||
with the Invariant Sections being @var{list their titles}, with the
|
|
||||||
Front-Cover Texts being @var{list}, and with the Back-Cover Texts being @var{list}.
|
|
||||||
A copy of the license is included in the section entitled ``GNU
|
|
||||||
Free Documentation License''.
|
|
||||||
@end group
|
|
||||||
@end smallexample
|
|
||||||
|
|
||||||
If you have no Invariant Sections, write ``with no Invariant Sections''
|
|
||||||
instead of saying which ones are invariant. If you have no
|
|
||||||
Front-Cover Texts, write ``no Front-Cover Texts'' instead of
|
|
||||||
``Front-Cover Texts being @var{list}''; likewise for Back-Cover Texts.
|
|
||||||
|
|
||||||
If your document contains nontrivial examples of program code, we
|
|
||||||
recommend releasing these examples in parallel under your choice of
|
|
||||||
free software license, such as the GNU General Public License,
|
|
||||||
to permit their use in free software.
|
|
||||||
|
|
||||||
@c Local Variables:
|
|
||||||
@c ispell-local-pdict: "ispell-dict"
|
|
||||||
@c End:
|
|
174
doc/gnupg.texi
174
doc/gnupg.texi
@ -1,174 +0,0 @@
|
|||||||
\input texinfo @c -*-texinfo-*-
|
|
||||||
@c %**start of header
|
|
||||||
@setfilename gnupg.info
|
|
||||||
|
|
||||||
@include version.texi
|
|
||||||
|
|
||||||
@macro copyrightnotice
|
|
||||||
Copyright @copyright{} 2002 Free Software Foundation, Inc.
|
|
||||||
@end macro
|
|
||||||
@macro permissionnotice
|
|
||||||
Permission is granted to copy, distribute and/or modify this document
|
|
||||||
under the terms of the GNU Free Documentation License, Version 1.1 or
|
|
||||||
any later version published by the Free Software Foundation; with the
|
|
||||||
Invariant Sections being ``GNU General Public License'', the Front-Cover
|
|
||||||
texts being (a) (see below), and with the Back-Cover Texts being (b)
|
|
||||||
(see below). A copy of the license is included in the section entitled
|
|
||||||
``GNU Free Documentation License''.
|
|
||||||
|
|
||||||
(a) The FSF's Front-Cover Text is:
|
|
||||||
|
|
||||||
A GNU Manual
|
|
||||||
|
|
||||||
(b) The FSF's Back-Cover Text is:
|
|
||||||
|
|
||||||
You have freedom to copy and modify this GNU Manual, like GNU
|
|
||||||
software. Copies published by the Free Software Foundation raise
|
|
||||||
funds for GNU development.
|
|
||||||
@end macro
|
|
||||||
|
|
||||||
|
|
||||||
@settitle Using the GNU Privacy Guard
|
|
||||||
|
|
||||||
@c Create a separate index for command line options.
|
|
||||||
@defcodeindex op
|
|
||||||
@c Merge the standard indexes into a single one.
|
|
||||||
@syncodeindex fn cp
|
|
||||||
@syncodeindex vr cp
|
|
||||||
@syncodeindex ky cp
|
|
||||||
@syncodeindex pg cp
|
|
||||||
@syncodeindex tp cp
|
|
||||||
|
|
||||||
@c printing stuff taken from gcc.
|
|
||||||
@macro gnupgtabopt{body}
|
|
||||||
@code{\body\}
|
|
||||||
@end macro
|
|
||||||
@macro gnupgoptlist{body}
|
|
||||||
@smallexample
|
|
||||||
\body\
|
|
||||||
@end smallexample
|
|
||||||
@end macro
|
|
||||||
@c Makeinfo handles the above macro OK, TeX needs manual line breaks;
|
|
||||||
@c they get lost at some point in handling the macro. But if @macro is
|
|
||||||
@c used here rather than @alias, it produces double line breaks.
|
|
||||||
@iftex
|
|
||||||
@alias gol = *
|
|
||||||
@end iftex
|
|
||||||
@ifnottex
|
|
||||||
@macro gol
|
|
||||||
@end macro
|
|
||||||
@end ifnottex
|
|
||||||
|
|
||||||
|
|
||||||
@c Change the font used for @def... commands, since the default
|
|
||||||
@c proportional one used is bad for names starting __.
|
|
||||||
@tex
|
|
||||||
\global\setfont\defbf\ttbshape{10}{\magstep1}
|
|
||||||
@end tex
|
|
||||||
|
|
||||||
@c %**end of header
|
|
||||||
|
|
||||||
@ifnottex
|
|
||||||
@dircategory GNU Utilities
|
|
||||||
@direntry
|
|
||||||
* gpg: (gnupg). OpenPGP encryption and signing tool.
|
|
||||||
* gpgsm: (gnupg). S/MIME encryption and signing tool.
|
|
||||||
@end direntry
|
|
||||||
This file documents the use and the internals of the GNU Privacy Guard.
|
|
||||||
|
|
||||||
This is Edition @value{EDITION}, last updated @value{UPDATED}, of
|
|
||||||
@cite{The `GNU Privacy Guard' Manual}, for Version @value{VERSION}.
|
|
||||||
@sp 1
|
|
||||||
Published by the Free Software Foundation@*
|
|
||||||
59 Temple Place - Suite 330@*
|
|
||||||
Boston, MA 02111-1307 USA
|
|
||||||
@sp 1
|
|
||||||
@copyrightnotice{}
|
|
||||||
@sp 1
|
|
||||||
@permissionnotice{}
|
|
||||||
@end ifnottex
|
|
||||||
|
|
||||||
@setchapternewpage odd
|
|
||||||
|
|
||||||
@titlepage
|
|
||||||
@title Using the GNU Privacy Guard
|
|
||||||
@subtitle Version @value{VERSION}
|
|
||||||
@subtitle @value{UPDATED}
|
|
||||||
@author Werner Koch @code{(wk@@gnupg.org)}
|
|
||||||
|
|
||||||
@page
|
|
||||||
@vskip 0pt plus 1filll
|
|
||||||
@copyrightnotice{}
|
|
||||||
@sp 2
|
|
||||||
@permissionnotice{}
|
|
||||||
@end titlepage
|
|
||||||
@summarycontents
|
|
||||||
@contents
|
|
||||||
@page
|
|
||||||
|
|
||||||
|
|
||||||
@node Top
|
|
||||||
@top Introduction
|
|
||||||
@cindex introduction
|
|
||||||
|
|
||||||
This manual documents how to use the GNU Privay Guard system as well as
|
|
||||||
the administration and the architecture.
|
|
||||||
|
|
||||||
@c * Gpg:: Using the OpenPGP protocol.
|
|
||||||
@menu
|
|
||||||
* Invoking GPGSM:: Using the S/MIME protocol.
|
|
||||||
* Invoking GPG-AGENT:: How to launch the secret key daemon.
|
|
||||||
* Invoking SCDAEMON:: How to handle Smartcards.
|
|
||||||
|
|
||||||
Developer information
|
|
||||||
|
|
||||||
* Assuan:: Description of the Assuan protocol.
|
|
||||||
|
|
||||||
Miscellaneous
|
|
||||||
|
|
||||||
* Debugging:: How to solve problems
|
|
||||||
* Copying:: GNU General Public License says
|
|
||||||
how you can copy and share GnuPG
|
|
||||||
* GNU Free Documentation License:: How you can copy and share this manual.
|
|
||||||
* Contributors:: People who have contributed to GnuPG.
|
|
||||||
|
|
||||||
Indices
|
|
||||||
|
|
||||||
* Option Index:: Index to command line options.
|
|
||||||
* Index:: Index of concepts and symbol names.
|
|
||||||
@end menu
|
|
||||||
|
|
||||||
@include gpgsm.texi
|
|
||||||
@include gpg-agent.texi
|
|
||||||
@include scdaemon.texi
|
|
||||||
|
|
||||||
@include assuan.texi
|
|
||||||
|
|
||||||
@include debugging.texi
|
|
||||||
|
|
||||||
@include gpl.texi
|
|
||||||
@include fdl.texi
|
|
||||||
|
|
||||||
@include contrib.texi
|
|
||||||
|
|
||||||
@c ---------------------------------------------------------------------
|
|
||||||
@c Indexes
|
|
||||||
@c ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
@node Option Index
|
|
||||||
@unnumbered Option Index
|
|
||||||
|
|
||||||
@printindex op
|
|
||||||
|
|
||||||
@node Index
|
|
||||||
@unnumbered Index
|
|
||||||
|
|
||||||
@printindex cp
|
|
||||||
|
|
||||||
@c ---------------------------------------------------------------------
|
|
||||||
@c Epilogue
|
|
||||||
@c ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
@bye
|
|
||||||
|
|
||||||
|
|
@ -1,791 +0,0 @@
|
|||||||
@c Copyright (C) 2002 Free Software Foundation, Inc.
|
|
||||||
@c This is part of the GnuPG manual.
|
|
||||||
@c For copying conditions, see the file gnupg.texi.
|
|
||||||
|
|
||||||
@node Invoking GPG-AGENT
|
|
||||||
@chapter Invoking GPG-AGENT
|
|
||||||
@cindex GPG-AGENT command options
|
|
||||||
@cindex command options
|
|
||||||
@cindex options, GPG-AGENT command
|
|
||||||
|
|
||||||
@c man begin DESCRIPTION
|
|
||||||
|
|
||||||
@sc{gpg-agent} is a daemon to manage secret (private) keys independelty
|
|
||||||
from any protocol. It is used as a backend for @sc{gpg} and @sc{gpgsm}
|
|
||||||
as well as for a couple of other utilities.
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
The usual way to run the agent is from the @code{~/.xsession} file:
|
|
||||||
|
|
||||||
@example
|
|
||||||
eval `gpg-agent --daemon`
|
|
||||||
@end example
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
If you don't use an X server, you can also put this into your regular
|
|
||||||
startup file @code{~/.profile} or @code{.bash_profile}. It is best not
|
|
||||||
to run multiple instance of the gpg-agent, so you should make sure that
|
|
||||||
only is running: @sc{gpg-agent} uses an environment variable to inform
|
|
||||||
clients about the communication parameters. You can write the
|
|
||||||
content of this environment variable to a file so that you can test for
|
|
||||||
a running agent. This short script may do the job:
|
|
||||||
|
|
||||||
@smallexample
|
|
||||||
if test -f $HOME/.gpg-agent-info && \
|
|
||||||
kill -0 `cut -d: -f 2 $HOME/.gpg-agent-info` 2>/dev/null; then
|
|
||||||
GPG_AGENT_INFO=`cat $HOME/.gpg-agent-info`
|
|
||||||
export GPG_AGENT_INFO
|
|
||||||
else
|
|
||||||
eval `gpg-agent --daemon`
|
|
||||||
echo $GPG_AGENT_INFO >$HOME/.gpg-agent-info
|
|
||||||
fi
|
|
||||||
@end smallexample
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
If you want to use a curses based pinentry (which is usually also the
|
|
||||||
fallback mode for a GUI based pinentry), you should add these lines to
|
|
||||||
your @code{.bashrc} or whatever initialization file is used for all shell
|
|
||||||
invocations:
|
|
||||||
|
|
||||||
@smallexample
|
|
||||||
GPG_TTY=`tty`
|
|
||||||
export GPG_TTY
|
|
||||||
@end smallexample
|
|
||||||
|
|
||||||
It is important that this environment variable always reflects the
|
|
||||||
output of the @code{tty} command.
|
|
||||||
|
|
||||||
@c man end
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
@xref{Option Index}, for an index to GPG-AGENTS's commands and options.
|
|
||||||
|
|
||||||
@menu
|
|
||||||
* Agent Commands:: List of all commands.
|
|
||||||
* Agent Options:: List of all options.
|
|
||||||
* Agent Signals:: Use of some signals.
|
|
||||||
* Agent Examples:: Some usage examples.
|
|
||||||
* Agent Protocol:: The protocol the agent uses.
|
|
||||||
@end menu
|
|
||||||
|
|
||||||
@c man begin COMMANDS
|
|
||||||
|
|
||||||
@node Agent Commands
|
|
||||||
@section Commands
|
|
||||||
|
|
||||||
Commands are not distinguished from options execpt for the fact that
|
|
||||||
only one one command is allowed.
|
|
||||||
|
|
||||||
@table @gnupgtabopt
|
|
||||||
@item --version
|
|
||||||
@opindex version
|
|
||||||
Print the program version and licensing information. Not that you can
|
|
||||||
abbreviate this command.
|
|
||||||
|
|
||||||
@item --help, -h
|
|
||||||
@opindex help
|
|
||||||
Print a usage message summarizing the most usefule command-line options.
|
|
||||||
Not that you can abbreviate this command.
|
|
||||||
|
|
||||||
@item --dump-options
|
|
||||||
@opindex dump-options
|
|
||||||
Print a list of all available options and commands. Not that you can
|
|
||||||
abbreviate this command.
|
|
||||||
|
|
||||||
@item --server
|
|
||||||
@opindex server
|
|
||||||
Run in server mode and wait for commands on the @code{stdin}. The
|
|
||||||
default mode is to create a socket and listen for commands there.
|
|
||||||
|
|
||||||
@item --daemon
|
|
||||||
@opindex daemon
|
|
||||||
Run the program in the background. This option is required to prevent
|
|
||||||
it from being accidently running in the background. A common way to do
|
|
||||||
this is:
|
|
||||||
@example
|
|
||||||
@end example
|
|
||||||
$ eval `gpg-agent --daemon`
|
|
||||||
@end table
|
|
||||||
|
|
||||||
|
|
||||||
@c man begin OPTIONS
|
|
||||||
|
|
||||||
@node Agent Options
|
|
||||||
@section Option Summary
|
|
||||||
|
|
||||||
@table @gnupgtabopt
|
|
||||||
|
|
||||||
@item --options @var{file}
|
|
||||||
@opindex options
|
|
||||||
Reads configuration from @var{file} instead of from the default
|
|
||||||
per-user configuration file. The default configuration file is named
|
|
||||||
@file{gpg-agent.conf} and expected in the @file{.gnupg} directory directly
|
|
||||||
below the home directory of the user.
|
|
||||||
|
|
||||||
@item -v
|
|
||||||
@item --verbose
|
|
||||||
@opindex v
|
|
||||||
@opindex verbose
|
|
||||||
Outputs additional information while running.
|
|
||||||
You can increase the verbosity by giving several
|
|
||||||
verbose commands to @sc{gpgsm}, such as @samp{-vv}.
|
|
||||||
|
|
||||||
@item -q
|
|
||||||
@item --quiet
|
|
||||||
@opindex q
|
|
||||||
@opindex quiet
|
|
||||||
Try to be as quiet as possible.
|
|
||||||
|
|
||||||
@item --batch
|
|
||||||
@opindex batch
|
|
||||||
Don't invoke a pinentry or do any other thing requiring human interaction.
|
|
||||||
|
|
||||||
@item --faked-system-time @var{epoch}
|
|
||||||
@opindex faked-system-time
|
|
||||||
This option is only useful for testing; it sets the system time back or
|
|
||||||
forth to @var{epoch} which is the number of seconds elapsed since the year
|
|
||||||
1970.
|
|
||||||
|
|
||||||
@item --debug-level @var{level}
|
|
||||||
@opindex debug-level
|
|
||||||
Select the debug level for investigating problems. @var{level} may be
|
|
||||||
one of:
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
@item none
|
|
||||||
no debugging at all.
|
|
||||||
@item basic
|
|
||||||
some basic debug messages
|
|
||||||
@item advanced
|
|
||||||
more verbose debug messages
|
|
||||||
@item expert
|
|
||||||
even more detailed messages
|
|
||||||
@item guru
|
|
||||||
all of the debug messages you can get
|
|
||||||
@end table
|
|
||||||
|
|
||||||
How these messages are mapped to the actual debugging flags is not
|
|
||||||
specified and may change with newer releaes of this program. They are
|
|
||||||
however carefully selected to best aid in debugging.
|
|
||||||
|
|
||||||
@item --debug @var{flags}
|
|
||||||
@opindex debug
|
|
||||||
This option is only useful for debugging and the behaviour may change at
|
|
||||||
any time without notice. FLAGS are bit encoded and may be given in
|
|
||||||
usual C-Syntax. The currently defined bits are:
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
@item 0 (1)
|
|
||||||
X.509 or OpenPGP protocol related data
|
|
||||||
@item 1 (2)
|
|
||||||
values of big number integers
|
|
||||||
@item 2 (4)
|
|
||||||
low level crypto operations
|
|
||||||
@item 5 (32)
|
|
||||||
memory allocation
|
|
||||||
@item 6 (64)
|
|
||||||
caching
|
|
||||||
@item 7 (128)
|
|
||||||
show memory statistics.
|
|
||||||
@item 9 (512)
|
|
||||||
write hashed data to files named @code{dbgmd-000*}
|
|
||||||
@item 10 (1024)
|
|
||||||
trace Assuan protocol
|
|
||||||
@item 12 (4096)
|
|
||||||
bypass all certificate validation
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@item --debug-all
|
|
||||||
@opindex debug-all
|
|
||||||
Same as @code{--debug=0xffffffff}
|
|
||||||
|
|
||||||
@item --debug-wait @var{n}
|
|
||||||
@opindex debug-wait
|
|
||||||
When running in server mode, wait @var{n} seconds before entering the
|
|
||||||
actual processing loop and print the pid. This gives time to attach a
|
|
||||||
debugger.
|
|
||||||
|
|
||||||
@item --no-detach
|
|
||||||
@opindex no-detach
|
|
||||||
Don't detach the process from the console. This is manly usefule for
|
|
||||||
debugging.
|
|
||||||
|
|
||||||
@item -s
|
|
||||||
@itemx --sh
|
|
||||||
@itemx -c
|
|
||||||
@itemx --csh
|
|
||||||
@opindex s
|
|
||||||
@opindex sh
|
|
||||||
@opindex c
|
|
||||||
@opindex csh
|
|
||||||
Format the info output in daemon mode for use with the standard Bourne
|
|
||||||
shell respective the C-shell . The default ist to guess it based on the
|
|
||||||
environment variable @code{SHELL} which is in almost all cases
|
|
||||||
sufficient.
|
|
||||||
|
|
||||||
@item --no-grab
|
|
||||||
@opindex no-grab
|
|
||||||
Tell the pinentryo not to grab the keyboard and mouse. This option
|
|
||||||
should in general not be used to avaoid X-sniffing attacks.
|
|
||||||
|
|
||||||
@item --log-file @var{file}
|
|
||||||
@opindex log-file
|
|
||||||
Append all logging output to @var{file}. This is very helpful in
|
|
||||||
seeing what the agent actually does.
|
|
||||||
|
|
||||||
@item --disable-pth
|
|
||||||
@opindex disable-pth
|
|
||||||
Don't allow multiple connections. This option is in general not very
|
|
||||||
useful.
|
|
||||||
|
|
||||||
@item --allow-mark-trusted
|
|
||||||
@opindex allow-mark-trusted
|
|
||||||
Allow clients to mark keys as trusted, i.e. put them into the
|
|
||||||
@code{trustlist.txt} file. This is by default not allowed to make it
|
|
||||||
harder for users to inadvertly accept Root-CA keys.
|
|
||||||
|
|
||||||
@item --ignore-cache-for-signing
|
|
||||||
@opindex ignore-cache-for-signing
|
|
||||||
This option will let gpg-agent bypass the passphrase cache for all
|
|
||||||
signing operation. Note that there is also a per-session option to
|
|
||||||
control this behaviour but this command line option takes precedence.
|
|
||||||
|
|
||||||
@item --default-cache-ttl @var{n}
|
|
||||||
@opindex default-cache-ttl
|
|
||||||
Set the time a cache entry is valid to @var{n} seconds. The default are
|
|
||||||
600 seconds.
|
|
||||||
|
|
||||||
@item --pinentry-program @var{filename}
|
|
||||||
@opindex pinentry-program
|
|
||||||
Use program @var{filename} as the PIN entry. The default is installation
|
|
||||||
dependend and can be shown with the @code{--version} command.
|
|
||||||
|
|
||||||
@item --scdaemon-program @var{filename}
|
|
||||||
@opindex scdaemon-program
|
|
||||||
Use program @var{filename} as the Smartcard daemon. The default is
|
|
||||||
installation dependend and can be shown with the @code{--version}
|
|
||||||
command.
|
|
||||||
|
|
||||||
|
|
||||||
@item --display @var{string}
|
|
||||||
@itemx --ttyname @var{string}
|
|
||||||
@itemx --ttytype @var{string}
|
|
||||||
@itemx --lc-type @var{string}
|
|
||||||
@itemx --lc-messages @var{string}
|
|
||||||
@opindex display
|
|
||||||
@opindex ttyname
|
|
||||||
@opindex ttytype
|
|
||||||
@opindex lc-type
|
|
||||||
@opindex lc-messa
|
|
||||||
These options are used with the server mode to pass localization
|
|
||||||
information.
|
|
||||||
|
|
||||||
@item --keep-tty
|
|
||||||
@itemx --keep-display
|
|
||||||
@opindex keep-tty
|
|
||||||
@opindex keep-display
|
|
||||||
Ignore requests to change change the current @sc{tty} respective the X
|
|
||||||
window system's @code{DISPLAY} variable. This is useful to lock the
|
|
||||||
pinentry to pop up at the @sc{tty} or display you started the agent.
|
|
||||||
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
All the long options may also be given in the configuration file after
|
|
||||||
stripping off the two leading dashes.
|
|
||||||
|
|
||||||
@c
|
|
||||||
@c Agent Signals
|
|
||||||
@c
|
|
||||||
@node Agent Signals
|
|
||||||
@section Use of some signals.
|
|
||||||
A running @command{gpg-agent} may be controlled by signals, i.e. using
|
|
||||||
the @command{kill} command to send a signal to the process.
|
|
||||||
|
|
||||||
Here is a list of supported signals:
|
|
||||||
|
|
||||||
@table @gnupgtabopt
|
|
||||||
|
|
||||||
@item SIGHUP
|
|
||||||
@cpindex SIGHUP
|
|
||||||
This signals flushes all chached passphrases and when the program was
|
|
||||||
started with a configuration file, the configuration file is read again.
|
|
||||||
Only certain options are honored: @code{quiet}, @code{verbose},
|
|
||||||
@code{debug}, @code{debug-all}, @code{no-grab}, @code{pinentry-program},
|
|
||||||
@code{default-cache-ttl} and @code{ignore-cache-for-signing}.
|
|
||||||
@code{scdaemon-program} is also supported but due to the current
|
|
||||||
implementation, which calls the scdaemon only once, it is not of much
|
|
||||||
use.
|
|
||||||
|
|
||||||
|
|
||||||
@item SIGTERM
|
|
||||||
@cpindex SIGTERM
|
|
||||||
Shuts down the process but waits until all current requests are
|
|
||||||
fulfilled. If the process has received 3 of these signals and requests
|
|
||||||
are still pending, a shutdown is forced.
|
|
||||||
|
|
||||||
@item SIGINT
|
|
||||||
@cpindex SIGINT
|
|
||||||
Shuts down the process immediately.
|
|
||||||
|
|
||||||
|
|
||||||
@item SIGUSR1
|
|
||||||
@itemx SIGUSR2
|
|
||||||
@cpindex SIGUSR1
|
|
||||||
@cpindex SIGUSR2
|
|
||||||
These signals are used for internal purposes.
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@c
|
|
||||||
@c Examples
|
|
||||||
@c
|
|
||||||
@node Agent Examples
|
|
||||||
@section Examples
|
|
||||||
|
|
||||||
@c man begin EXAMPLES
|
|
||||||
|
|
||||||
@example
|
|
||||||
$ eval `gpg-agent --daemon`
|
|
||||||
@end example
|
|
||||||
|
|
||||||
@c man end
|
|
||||||
|
|
||||||
|
|
||||||
@c
|
|
||||||
@c Assuan Protocol
|
|
||||||
@c
|
|
||||||
@node Agent Protocol
|
|
||||||
@section Agent's Assuan Protocol
|
|
||||||
|
|
||||||
The gpg-agent should be started by the login shell and set an
|
|
||||||
environment variable to tell clients about the socket to be used.
|
|
||||||
Clients should deny to access an agent with a socket name which does
|
|
||||||
not match its own configuration. An application may choose to start
|
|
||||||
an instance of the gpgagent if it does not figure that any has been
|
|
||||||
started; it should not do this if a gpgagent is running but not
|
|
||||||
usable. Because gpg-agent can only be used in background mode, no
|
|
||||||
special command line option is required to activate the use of the
|
|
||||||
protocol.
|
|
||||||
|
|
||||||
To identify a key we use a thing called keygrip which is the SHA-1 hash
|
|
||||||
of an canoncical encoded S-Expression of the the public key as used in
|
|
||||||
Libgcrypt. For the purpose of this interface the keygrip is given as a
|
|
||||||
hex string. The advantage of using this and not the hash of a
|
|
||||||
certificate is that it will be possible to use the same keypair for
|
|
||||||
different protocols, thereby saving space on the token used to keep the
|
|
||||||
secret keys.
|
|
||||||
|
|
||||||
@menu
|
|
||||||
* Agent PKDECRYPT:: Decrypting a session key
|
|
||||||
* Agent PKSIGN:: Signing a Hash
|
|
||||||
* Agent GENKEY:: Generating a Key
|
|
||||||
* Agent IMPORT:: Importing a Secret Key
|
|
||||||
* Agent EXPORT:: Exporting a Secret Key
|
|
||||||
* Agent ISTRUSTED:: Importing a Root Certificate
|
|
||||||
* Agent GET_PASSPHRASE:: Ask for a passphrase
|
|
||||||
* Agent GET_CONFIRMATION:: Ask for confirmation
|
|
||||||
* Agent HAVEKEY:: Check whether a key is available
|
|
||||||
* Agent LEARN:: Register a smartcard
|
|
||||||
* Agent PASSWD:: Change a Passphrase
|
|
||||||
@end menu
|
|
||||||
|
|
||||||
@node Agent PKDECRYPT
|
|
||||||
@subsection Decrypting a session key
|
|
||||||
|
|
||||||
The client asks the server to decrypt a session key. The encrypted
|
|
||||||
session key should have all information needed to select the
|
|
||||||
appropriate secret key or to delegate it to a smartcard.
|
|
||||||
|
|
||||||
@example
|
|
||||||
SETKEY <keyGrip>
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Tell the server about the key to be used for decryption. If this is
|
|
||||||
not used, gpg-agent may try to figure out the key by trying to
|
|
||||||
decrypt the message with each key available.
|
|
||||||
|
|
||||||
@example
|
|
||||||
PKDECRYPT
|
|
||||||
@end example
|
|
||||||
|
|
||||||
The agent checks whether this command is allowed and then does an
|
|
||||||
INQUIRY to get the ciphertext the client should then send the cipher
|
|
||||||
text.
|
|
||||||
|
|
||||||
@example
|
|
||||||
S: INQUIRE CIPHERTEXT
|
|
||||||
C: D (xxxxxx
|
|
||||||
C: D xxxx)
|
|
||||||
C: END
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Please note that the server may send status info lines while reading the
|
|
||||||
data lines from the client. The data send is a SPKI like S-Exp with
|
|
||||||
this structure:
|
|
||||||
|
|
||||||
@example
|
|
||||||
(enc-val
|
|
||||||
(<algo>
|
|
||||||
(<param_name1> <mpi>)
|
|
||||||
...
|
|
||||||
(<param_namen> <mpi>)))
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Where algo is a string with the name of the algorithm; see the libgcrypt
|
|
||||||
documentation for a list of valid algorithms. The number and names of
|
|
||||||
the parameters depend on the algorithm. The agent does return an error
|
|
||||||
if there is an inconsistency.
|
|
||||||
|
|
||||||
If the decryption was successful the decrypted data is returned by
|
|
||||||
means of "D" lines.
|
|
||||||
|
|
||||||
Here is an example session:
|
|
||||||
|
|
||||||
@example
|
|
||||||
C: PKDECRYPT
|
|
||||||
S: INQUIRE CIPHERTEXT
|
|
||||||
C: D (enc-val elg (a 349324324)
|
|
||||||
C: D (b 3F444677CA)))
|
|
||||||
C: END
|
|
||||||
S: # session key follows
|
|
||||||
S: D 1234567890ABCDEF0
|
|
||||||
S: OK descryption successful
|
|
||||||
@end example
|
|
||||||
|
|
||||||
|
|
||||||
@node Agent PKSIGN
|
|
||||||
@subsection Signing a Hash
|
|
||||||
|
|
||||||
The client ask the agent to sign a given hash value. A default key
|
|
||||||
will be chosen if no key has been set. To set a key a client first
|
|
||||||
uses:
|
|
||||||
|
|
||||||
@example
|
|
||||||
SIGKEY <keyGrip>
|
|
||||||
@end example
|
|
||||||
|
|
||||||
This can be used multiple times to create multiple signature, the list
|
|
||||||
of keys is reset with the next PKSIGN command or a RESET. The server
|
|
||||||
test whether the key is a valid key to sign something and responds with
|
|
||||||
okay.
|
|
||||||
|
|
||||||
@example
|
|
||||||
SETHASH <hexstring>
|
|
||||||
@end example
|
|
||||||
|
|
||||||
The client can use this command to tell the server about the data
|
|
||||||
(which usually is a hash) to be signed.
|
|
||||||
|
|
||||||
The actual signing is done using
|
|
||||||
|
|
||||||
@example
|
|
||||||
PKSIGN <options>
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Options are not yet defined, but my later be used to choosen among
|
|
||||||
different algorithms (e.g. pkcs 1.5)
|
|
||||||
|
|
||||||
The agent does then some checks, asks for the passphrase and
|
|
||||||
if SETHASH has not been used asks the client for the data to sign:
|
|
||||||
|
|
||||||
@example
|
|
||||||
S: INQUIRE HASHVAL
|
|
||||||
C: D ABCDEF012345678901234
|
|
||||||
C: END
|
|
||||||
@end example
|
|
||||||
|
|
||||||
As a result the server returns the signature as an SPKI like S-Exp
|
|
||||||
in "D" lines:
|
|
||||||
|
|
||||||
@example
|
|
||||||
(sig-val
|
|
||||||
(<algo>
|
|
||||||
(<param_name1> <mpi>)
|
|
||||||
...
|
|
||||||
(<param_namen> <mpi>)))
|
|
||||||
@end example
|
|
||||||
|
|
||||||
|
|
||||||
The operation is affected by the option
|
|
||||||
|
|
||||||
@example
|
|
||||||
OPTION use-cache-for-signing=0|1
|
|
||||||
@end example
|
|
||||||
|
|
||||||
The default of @code{1} uses the cache. Setting this option to @code{0}
|
|
||||||
will lead gpg-agent to ignore the passphrase cache. Note, that there is
|
|
||||||
also a global command line option for gpg-agent to globally disable the
|
|
||||||
caching.
|
|
||||||
|
|
||||||
|
|
||||||
Here is an example session:
|
|
||||||
|
|
||||||
@example
|
|
||||||
C: SIGKEY <keyGrip>
|
|
||||||
S: OK key available
|
|
||||||
C: SIGKEY <keyGrip>
|
|
||||||
S: OK key available
|
|
||||||
C: PKSIGN
|
|
||||||
S: # I did ask the user whether he really wants to sign
|
|
||||||
S: # I did ask the user for the passphrase
|
|
||||||
S: INQUIRE HASHVAL
|
|
||||||
C: D ABCDEF012345678901234
|
|
||||||
C: END
|
|
||||||
S: # signature follows
|
|
||||||
S: D (sig-val rsa (s 45435453654612121212))
|
|
||||||
S: OK
|
|
||||||
@end example
|
|
||||||
|
|
||||||
|
|
||||||
@node Agent GENKEY
|
|
||||||
@subsection Generating a Key
|
|
||||||
|
|
||||||
This is used to create a new keypair and store the secret key inside the
|
|
||||||
active PSE -w which is in most cases a Soft-PSE. An not yet defined
|
|
||||||
option allows to choose the storage location. To get the secret key out
|
|
||||||
of the PSE, a special export tool has to be used.
|
|
||||||
|
|
||||||
@example
|
|
||||||
GENKEY
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Invokes the key generation process and the server will then inquire
|
|
||||||
on the generation parameters, like:
|
|
||||||
|
|
||||||
@example
|
|
||||||
S: INQUIRE KEYPARM
|
|
||||||
C: D (genkey (rsa (nbits 1024)))
|
|
||||||
C: END
|
|
||||||
@end example
|
|
||||||
|
|
||||||
The format of the key parameters which depends on the algorithm is of
|
|
||||||
the form:
|
|
||||||
|
|
||||||
@example
|
|
||||||
(genkey
|
|
||||||
(algo
|
|
||||||
(parameter_name_1 ....)
|
|
||||||
....
|
|
||||||
(parameter_name_n ....)))
|
|
||||||
@end example
|
|
||||||
|
|
||||||
If everything succeeds, the server returns the *public key* in a SPKI
|
|
||||||
like S-Expression like this:
|
|
||||||
|
|
||||||
@example
|
|
||||||
(public-key
|
|
||||||
(rsa
|
|
||||||
(n <mpi>)
|
|
||||||
(e <mpi>)))
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Here is an example session:
|
|
||||||
|
|
||||||
@example
|
|
||||||
C: GENKEY
|
|
||||||
S: INQUIRE KEYPARM
|
|
||||||
C: D (genkey (rsa (nbits 1024)))
|
|
||||||
C: END
|
|
||||||
S: D (public-key
|
|
||||||
S: D (rsa (n 326487324683264) (e 10001)))
|
|
||||||
S OK key created
|
|
||||||
@end example
|
|
||||||
|
|
||||||
@node Agent IMPORT
|
|
||||||
@subsection Importing a Secret Key
|
|
||||||
|
|
||||||
This operation is not yet supportted by GpgAgent. Specialized tools
|
|
||||||
are to be used for this.
|
|
||||||
|
|
||||||
There is no actual need because we can expect that secret keys
|
|
||||||
created by a 3rd party are stored on a smartcard. If we have
|
|
||||||
generated the key ourself, we do not need to import it.
|
|
||||||
|
|
||||||
@node Agent EXPORT
|
|
||||||
@subsection Export a Secret Key
|
|
||||||
|
|
||||||
Not implemented.
|
|
||||||
|
|
||||||
Should be done by an extra tool.
|
|
||||||
|
|
||||||
@node Agent ISTRUSTED
|
|
||||||
@subsection Importing a Root Certificate
|
|
||||||
|
|
||||||
Actually we do not import a Root Cert but provide a way to validate
|
|
||||||
any piece of data by storing its Hash along with a description and
|
|
||||||
an identifier in the PSE. Here is the interface desription:
|
|
||||||
|
|
||||||
@example
|
|
||||||
ISTRUSTED <fingerprint>
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Check whether the OpenPGP primary key or the X.509 certificate with the
|
|
||||||
given fingerprint is an ultimately trusted key or a trusted Root CA
|
|
||||||
certificate. The fingerprint should be given as a hexstring (without
|
|
||||||
any blanks or colons or whatever in between) and may be left padded with
|
|
||||||
00 in case of an MD5 fingerprint. GPGAgent will answer with:
|
|
||||||
|
|
||||||
@example
|
|
||||||
OK
|
|
||||||
@end example
|
|
||||||
|
|
||||||
The key is in the table of trusted keys.
|
|
||||||
|
|
||||||
@example
|
|
||||||
ERR 304 (Not Trusted)
|
|
||||||
@end example
|
|
||||||
|
|
||||||
The key is not in this table.
|
|
||||||
|
|
||||||
Gpg needs the entire list of trusted keys to maintain the web of
|
|
||||||
trust; the following command is therefore quite helpful:
|
|
||||||
|
|
||||||
@example
|
|
||||||
LISTTRUSTED
|
|
||||||
@end example
|
|
||||||
|
|
||||||
GpgAgent returns a list of trusted keys line by line:
|
|
||||||
|
|
||||||
@example
|
|
||||||
S: D 000000001234454556565656677878AF2F1ECCFF P
|
|
||||||
S: D 340387563485634856435645634856438576457A P
|
|
||||||
S: D FEDC6532453745367FD83474357495743757435D S
|
|
||||||
S: OK
|
|
||||||
@end example
|
|
||||||
|
|
||||||
The first item on a line is the hexified fingerprint where MD5
|
|
||||||
ingerprints are @code{00} padded to the left and the second item is a
|
|
||||||
flag to indicate the type of key (so that gpg is able to only take care
|
|
||||||
of PGP keys). P = OpenPGP, S = S/MIME. A client should ignore the rest
|
|
||||||
of the line, so that we can extend the format in the future.
|
|
||||||
|
|
||||||
Finally a client should be able to mark a key as trusted:
|
|
||||||
|
|
||||||
@example
|
|
||||||
MARKTRUSTED @var{fingerprint} "P"|"S"
|
|
||||||
@end example
|
|
||||||
|
|
||||||
The server will then pop up a window to ask the user whether she
|
|
||||||
really trusts this key. For this it will probably ask for a text to
|
|
||||||
be displayed like this:
|
|
||||||
|
|
||||||
@example
|
|
||||||
S: INQUIRE TRUSTDESC
|
|
||||||
C: D Do you trust the key with the fingerprint @@FPR@@
|
|
||||||
C: D bla fasel blurb.
|
|
||||||
C: END
|
|
||||||
S: OK
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Known sequences with the pattern @@foo@@ are replaced according to this
|
|
||||||
table:
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
@item @@FPR16@@
|
|
||||||
Format the fingerprint according to gpg rules for a v3 keys.
|
|
||||||
@item @@FPR20@@
|
|
||||||
Format the fingerprint according to gpg rules for a v4 keys.
|
|
||||||
@item @@FPR@@
|
|
||||||
Choose an appropriate format to format the fingerprint.
|
|
||||||
@item @@@@
|
|
||||||
Replaced by a single @code{@@}
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@node Agent GET_PASSPHRASE
|
|
||||||
@subsection Ask for a passphrase
|
|
||||||
|
|
||||||
This function is usually used to ask for a passphrase to be used for
|
|
||||||
conventional encryption, but may also be used by programs which need
|
|
||||||
special handling of passphrases. This command uses a syntax which helps
|
|
||||||
clients to use the agent with minimum effort.
|
|
||||||
|
|
||||||
@example
|
|
||||||
GET_PASSPHRASE @var{cache_id} [@var{error_message} @var{prompt} @var{description}]
|
|
||||||
@end example
|
|
||||||
|
|
||||||
@var{cache_id} is expected to be a hex string used for caching a
|
|
||||||
passphrase. Use a @code{X} to bypass the cache. With no other
|
|
||||||
arguments the agent returns a cached passphrase or an error.
|
|
||||||
|
|
||||||
@var{error_message} is either a single @code{X} for no error message or
|
|
||||||
a string to be shown as an error message like (e.g. "invalid
|
|
||||||
passphrase"). Blanks must be percent escaped or replaced by @code{+}'.
|
|
||||||
|
|
||||||
@var{prompt} is either a single @code{X} for a default prompt or the
|
|
||||||
text to be shown as the prompt. Blanks must be percent escaped or
|
|
||||||
replaced by @code{+}.
|
|
||||||
|
|
||||||
@var{description} is a text shown above the entry field. Blanks must be
|
|
||||||
percent escaped or replaced by @code{+}.
|
|
||||||
|
|
||||||
The agent either returns with an error or with a OK followed by the
|
|
||||||
hex encoded passphrase. Note that the length of the strings is
|
|
||||||
implicitly limited by the maximum length of a command.
|
|
||||||
|
|
||||||
@example
|
|
||||||
CLEAR_PASSPHRASE @var{cache_id}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
may be used to invalidate the cache entry for a passphrase. The
|
|
||||||
function returns with OK even when there is no cached passphrase.
|
|
||||||
|
|
||||||
|
|
||||||
@node Agent GET_CONFIRMATION
|
|
||||||
@subsection Ask for confirmation
|
|
||||||
|
|
||||||
This command may be used to ask for a simple confirmation by
|
|
||||||
presenting a text and 2 bottonts: Okay and Cancel.
|
|
||||||
|
|
||||||
@example
|
|
||||||
GET_CONFIRMATION @var{description}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
@var{description}is displayed along with a Okay and Cancel
|
|
||||||
button. Blanks must be percent escaped or replaced by @code{+}. A
|
|
||||||
@code{X} may be used to display confirmation dialog with a default
|
|
||||||
text.
|
|
||||||
|
|
||||||
The agent either returns with an error or with a OK. Note, that the
|
|
||||||
length of @var{description} is implicitly limited by the maximum
|
|
||||||
length of a command.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@node Agent HAVEKEY
|
|
||||||
@subsection Check whether a key is available
|
|
||||||
|
|
||||||
This can be used to see whether a secret key is available. It does
|
|
||||||
not return any information on whether the key is somehow protected.
|
|
||||||
|
|
||||||
@example
|
|
||||||
HAVEKEY @var{keygrip}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
The Agent answers either with OK or @code{No_Secret_Key} (208). The
|
|
||||||
caller may want to check for other error codes as well.
|
|
||||||
|
|
||||||
|
|
||||||
@node Agent LEARN
|
|
||||||
@subsection Register a smartcard
|
|
||||||
|
|
||||||
@example
|
|
||||||
LEARN [--send]
|
|
||||||
@end example
|
|
||||||
|
|
||||||
This command is used to register a smartcard. With the --send
|
|
||||||
option given the certificates are send back.
|
|
||||||
|
|
||||||
|
|
||||||
@node Agent PASSWD
|
|
||||||
@subsection Change a Passphrase
|
|
||||||
|
|
||||||
@example
|
|
||||||
PASSWD @var{keygrip}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
This command is used to interactively change the passphrase of the key
|
|
||||||
indentified by the hex string @var{keygrip}.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
1806
doc/gpg.texi
1806
doc/gpg.texi
File diff suppressed because it is too large
Load Diff
848
doc/gpgsm.texi
848
doc/gpgsm.texi
@ -1,848 +0,0 @@
|
|||||||
@c Copyright (C) 2002 Free Software Foundation, Inc.
|
|
||||||
@c This is part of the GnuPG manual.
|
|
||||||
@c For copying conditions, see the file gnupg.texi.
|
|
||||||
|
|
||||||
@node Invoking GPGSM
|
|
||||||
@chapter Invoking GPGSM
|
|
||||||
@cindex GPGSM command options
|
|
||||||
@cindex command options
|
|
||||||
@cindex options, GPGSM command
|
|
||||||
|
|
||||||
@c man begin DESCRIPTION
|
|
||||||
|
|
||||||
@sc{gpgsm} is a tool similar to @sc{gpg} to provide digital encryption
|
|
||||||
and signing servicesd on X.509 certificates and the CMS protocoll. It
|
|
||||||
is mainly used as a backend for S/MIME mail processing. @sc{gpgsm}
|
|
||||||
includes a full features certificate management and complies with all
|
|
||||||
rules defined for the German Sphinx project.
|
|
||||||
|
|
||||||
@c man end
|
|
||||||
|
|
||||||
@xref{Option Index}, for an index to GPGSM's commands and options.
|
|
||||||
|
|
||||||
@menu
|
|
||||||
* GPGSM Commands:: List of all commands.
|
|
||||||
* GPGSM Options:: List of all options.
|
|
||||||
* GPGSM Examples:: Some usage examples.
|
|
||||||
|
|
||||||
Developer information:
|
|
||||||
* Unattended Usage:: Using @sc{gpgsm} from other programs.
|
|
||||||
* GPGSM Protocol:: The protocol the server mode uses.
|
|
||||||
@end menu
|
|
||||||
|
|
||||||
@c man begin COMMANDS
|
|
||||||
|
|
||||||
@node GPGSM Commands
|
|
||||||
@section Commands
|
|
||||||
|
|
||||||
Commands are not distinguished from options execpt for the fact that
|
|
||||||
only one one command is allowed.
|
|
||||||
|
|
||||||
@menu
|
|
||||||
* General Commands:: Commands not specific to the functionality.
|
|
||||||
* Operational Commands:: Commands to select the type of operation.
|
|
||||||
* Certificate Management:: How to manage certificates.
|
|
||||||
@end menu
|
|
||||||
|
|
||||||
@node General Commands
|
|
||||||
@subsection Commands not specific to the function
|
|
||||||
|
|
||||||
@table @gnupgtabopt
|
|
||||||
@item --version
|
|
||||||
@opindex version
|
|
||||||
Print the program version and licensing information. Not that you can
|
|
||||||
abbreviate this command.
|
|
||||||
|
|
||||||
@item --help, -h
|
|
||||||
@opindex help
|
|
||||||
Print a usage message summarizing the most usefule command-line options.
|
|
||||||
Not that you can abbreviate this command.
|
|
||||||
|
|
||||||
@item --dump-options
|
|
||||||
@opindex dump-options
|
|
||||||
Print a list of all available options and commands. Not that you can
|
|
||||||
abbreviate this command.
|
|
||||||
@end table
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@node Operational Commands
|
|
||||||
@subsection Commands to select the type of operation
|
|
||||||
|
|
||||||
@table @gnupgtabopt
|
|
||||||
@item --encrypt
|
|
||||||
@opindex encrypt
|
|
||||||
Perform an encryption.
|
|
||||||
|
|
||||||
@item --decrypt
|
|
||||||
@opindex decrypt
|
|
||||||
Perform a decryption; the type of input is automatically detmerined. It
|
|
||||||
may either be in binary form or PEM encoded; automatic determination of
|
|
||||||
base-64 encoding is not done.
|
|
||||||
|
|
||||||
@item --sign
|
|
||||||
@opindex sign
|
|
||||||
Create a digital signature. The key used is either the fist one found
|
|
||||||
in the keybox or thise set with the -u option
|
|
||||||
|
|
||||||
@item --verify
|
|
||||||
@opindex verify
|
|
||||||
Check a signature file for validity. Depending on the arguments a
|
|
||||||
detached signatrue may also be checked.
|
|
||||||
|
|
||||||
@item --server
|
|
||||||
@opindex server
|
|
||||||
Run in server mode and wait for commands on the @code{stdin}.
|
|
||||||
|
|
||||||
@item --call-dirmngr @var{command} [@var{args}]
|
|
||||||
@opindex call-dirmngr
|
|
||||||
Behave as a Dirmngr client issuing the request @var{command} with the
|
|
||||||
optional list of @var{args}. The output of the Dirmngr is printed
|
|
||||||
stdout. Please note that file names given as arguments should have an
|
|
||||||
absulte file name (i.e. commencing with @code{/} because they are
|
|
||||||
passed verbatim to the Dirmngr and the working directory of the
|
|
||||||
Dirmngr might not be the same as the one of this client. Currently it
|
|
||||||
is not possible to pass data via stdin to the Dirmngr. @var{command}
|
|
||||||
should not contain spaces.
|
|
||||||
|
|
||||||
This is command is required for certain maintaining tasks of the dirmngr
|
|
||||||
where a dirmngr must be able to call back to gpgsm. See the Dirmngr
|
|
||||||
manual for details.
|
|
||||||
|
|
||||||
@item --call-protect-tool @var{arguments}
|
|
||||||
@opindex call-protect-tool
|
|
||||||
Certain maintenance operations are done by an external program call
|
|
||||||
@command{gpg-protect-tool}; this is usually not installed in a directory
|
|
||||||
listed in the PATH variable. This command provides a simple wrapper to
|
|
||||||
access this tool. @var{arguments} are passed verbatim to this command;
|
|
||||||
use @samp{--help} to get a list of supported operations.
|
|
||||||
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
|
|
||||||
@node Certificate Management
|
|
||||||
@subsection How to manage the certificate and keys
|
|
||||||
|
|
||||||
@table @gnupgtabopt
|
|
||||||
@item --gen-key
|
|
||||||
@opindex gen-key
|
|
||||||
Generate a new key and a certificate request.
|
|
||||||
|
|
||||||
@item --list-keys
|
|
||||||
@itemx -k
|
|
||||||
@opindex list-keys
|
|
||||||
List all available certificates stored in the local key database.
|
|
||||||
|
|
||||||
@item --list-secret-keys
|
|
||||||
@itemx -K
|
|
||||||
@opindex list-secret-keys
|
|
||||||
List all available certificates for which a corresponding a secret key
|
|
||||||
is available.
|
|
||||||
|
|
||||||
@item --list-external-keys @var{pattern}
|
|
||||||
@opindex list-keys
|
|
||||||
List certificates matching @var{pattern} using an external server. This
|
|
||||||
utilizes the @code{dirmngr} service.
|
|
||||||
|
|
||||||
@item --dump-keys
|
|
||||||
@opindex dump-keys
|
|
||||||
List all available certificates stored in the local key database using a
|
|
||||||
format useful mainly for debugging.
|
|
||||||
|
|
||||||
@item --dump-secret-keys
|
|
||||||
@opindex dump-secret-keys
|
|
||||||
List all available certificates for which a corresponding a secret key
|
|
||||||
is available using a format useful mainly for debugging.
|
|
||||||
|
|
||||||
@item --dump-external-keys @var{pattern}
|
|
||||||
@opindex dump-keys
|
|
||||||
List certificates matching @var{pattern} using an external server.
|
|
||||||
This utilizes the @code{dirmngr} service. It uses a format useful
|
|
||||||
mainly for debugging.
|
|
||||||
|
|
||||||
@item --keydb-clear-some-cert-flags
|
|
||||||
@opindex keydb-clear-some-cert-flags
|
|
||||||
This is a debugging aid to reset certain flags in the key database
|
|
||||||
which are used to cache certain certificate stati. It is especially
|
|
||||||
useful if a bad CRL or a weird running OCSP reponder did accidently
|
|
||||||
revoke certificate. There is no security issue with this command
|
|
||||||
because gpgsm always make sure that the validity of a certificate is
|
|
||||||
checked right before it is used.
|
|
||||||
|
|
||||||
@item --delete-keys @var{pattern}
|
|
||||||
@opindex delete-keys
|
|
||||||
Delete the keys matching @var{pattern}.
|
|
||||||
|
|
||||||
@item --export [@var{pattern}]
|
|
||||||
@opindex export
|
|
||||||
Export all certificates stored in the Keybox or those specified by the
|
|
||||||
optional @var{pattern}. When using along with the @code{--armor} option
|
|
||||||
a few informational lines are prepended before each block.
|
|
||||||
|
|
||||||
@item --export-secret-key-p12 @var{key-id}
|
|
||||||
@opindex export
|
|
||||||
Export the private key and the certificate identified by @var{key-id}
|
|
||||||
in a PKCS#12 format. When using along with the @code{--armor} option
|
|
||||||
a few informational lines are prepended to the output. Note, that the
|
|
||||||
PKCS#12 format is higly insecure and this command is only provided if
|
|
||||||
there is no other way to exchange the private key.
|
|
||||||
|
|
||||||
@item --learn-card
|
|
||||||
@opindex learn-card
|
|
||||||
Read information about the private keys from the smartcard and import
|
|
||||||
the certificates from there. This command utilizes the @sc{gpg-agent}
|
|
||||||
and in turn the @sc{scdaemon}.
|
|
||||||
|
|
||||||
@item --passwd @var{user_id}
|
|
||||||
@opindex passwd
|
|
||||||
Change the passphrase of the private key belonging to the certificate
|
|
||||||
specified as @var{user_id}. Note, that changing the passphrase/PIN of a
|
|
||||||
smartcard is not yet supported.
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
|
|
||||||
@node GPGSM Options
|
|
||||||
@section Option Summary
|
|
||||||
|
|
||||||
GPGSM comes features a bunch ofoptions to control the exact behaviour
|
|
||||||
and to change the default configuration.
|
|
||||||
|
|
||||||
@menu
|
|
||||||
* Configuration Options:: How to change the configuration.
|
|
||||||
* Certificate Options:: Certificate related options.
|
|
||||||
* Input and Output:: Input and Output.
|
|
||||||
* CMS Options:: How to change how the CMS is created.
|
|
||||||
* Esoteric Options:: Doing things one usually don't want to do.
|
|
||||||
@end menu
|
|
||||||
|
|
||||||
@c man begin OPTIONS
|
|
||||||
|
|
||||||
@node Configuration Options
|
|
||||||
@subsection How to change the configuration
|
|
||||||
|
|
||||||
These options are used to change the configuraton and are usually found
|
|
||||||
in the option file.
|
|
||||||
|
|
||||||
@table @gnupgtabopt
|
|
||||||
|
|
||||||
@item --options @var{file}
|
|
||||||
@opindex options
|
|
||||||
Reads configuration from @var{file} instead of from the default
|
|
||||||
per-user configuration file. The default configuration file is named
|
|
||||||
@file{gpgsm.conf} and expected in the @file{.gnupg} directory directly
|
|
||||||
below the home directory of the user.
|
|
||||||
|
|
||||||
@item -v
|
|
||||||
@item --verbose
|
|
||||||
@opindex v
|
|
||||||
@opindex verbose
|
|
||||||
Outputs additional information while running.
|
|
||||||
You can increase the verbosity by giving several
|
|
||||||
verbose commands to @sc{gpgsm}, such as @samp{-vv}.
|
|
||||||
|
|
||||||
@item --policy-file @var{filename}
|
|
||||||
@opindex policy-file
|
|
||||||
Change the default name of the policy file to @var{filename}.
|
|
||||||
|
|
||||||
@item --agent-program @var{file}
|
|
||||||
@opindex agent-program
|
|
||||||
Specify an agent program to be used for secret key operations. The
|
|
||||||
default value is the @file{/usr/local/bin/gpg-agent}. This is only used
|
|
||||||
as a fallback when the envrionment variable @code{GPG_AGENT_INFO} is not
|
|
||||||
set or a running agent can't be connected.
|
|
||||||
|
|
||||||
@item --dirmngr-program @var{file}
|
|
||||||
@opindex dirmnr-program
|
|
||||||
Specify a dirmngr program to be used for @acronym{CRL} checks. The
|
|
||||||
default value is @file{/usr/sbin/dirmngr}. This is only used as a
|
|
||||||
fallback when the environment variable @code{DIRMNGR_INFO} is not set or
|
|
||||||
a running dirmngr can't be connected.
|
|
||||||
|
|
||||||
@item --no-secmem-warning
|
|
||||||
@opindex no-secmem-warning
|
|
||||||
Don't print a warning when the so called "secure memory" can't be used.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
|
|
||||||
@node Certificate Options
|
|
||||||
@subsection Certificate related options
|
|
||||||
|
|
||||||
@table @gnupgtabopt
|
|
||||||
|
|
||||||
@item --enable-policy-checks
|
|
||||||
@itemx --disable-policy-checks
|
|
||||||
@opindex enable-policy-checks
|
|
||||||
@opindex disable-policy-checks
|
|
||||||
By default policy checks are enabled. These options may be used to
|
|
||||||
change it.
|
|
||||||
|
|
||||||
@item --enable-crl-checks
|
|
||||||
@itemx --disable-crl-checks
|
|
||||||
@opindex enable-crl-checks
|
|
||||||
@opindex disable-crl-checks
|
|
||||||
By default the @acronym{CRL} checks are enabled and the DirMngr is used
|
|
||||||
to check for revoked certificates. The disable option is most useful
|
|
||||||
with an off-line network connection to suppress this check.
|
|
||||||
|
|
||||||
@item --force-crl-refresh
|
|
||||||
@opindex force-crl-refresh
|
|
||||||
Tell the dirmngr to reload the CRL for each request. For better
|
|
||||||
performance, the dirmngr will actually optimize this by suppressing
|
|
||||||
the loading for short time intervalls (e.g. 30 minutes). This option
|
|
||||||
is useful to make sure that a fresh CRL is available for certificates
|
|
||||||
hold in the keybox. The suggested way of doing this is by using it
|
|
||||||
along with the option @code{--with-validation} for a ke listing
|
|
||||||
command. This option should not be used in a configuration file.
|
|
||||||
|
|
||||||
@item --enable-ocsp
|
|
||||||
@itemx --disable-ocsp
|
|
||||||
@opindex enable-ocsp
|
|
||||||
@opindex disable-ocsp
|
|
||||||
Be default @acronym{OCSP} checks are disabled. The enable opton may
|
|
||||||
be used to enable OCSP checks via Dirmngr. If @acronym{CRL} checks
|
|
||||||
are also enabled, CRLs willbe used as a fallback if for some reason an
|
|
||||||
OCSP request won't succeed.
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@node Input and Output
|
|
||||||
@subsection Input and Output
|
|
||||||
|
|
||||||
@table @gnupgtabopt
|
|
||||||
@item --armor
|
|
||||||
@itemx -a
|
|
||||||
@opindex armor
|
|
||||||
@opindex -a
|
|
||||||
Create PEM encoded output. Default is binary output.
|
|
||||||
|
|
||||||
@item --base64
|
|
||||||
@opindex base64
|
|
||||||
Create Base-64 encoded output; i.e. PEM without the header lines.
|
|
||||||
|
|
||||||
@item --assume-armor
|
|
||||||
@opindex assume-armor
|
|
||||||
Assume the input data is PEM encoded. Default is to autodetect the
|
|
||||||
encoding but this is may fail.
|
|
||||||
|
|
||||||
@item --assume-base64
|
|
||||||
@opindex assume-base64
|
|
||||||
Assume the input data is plain base-64 encoded.
|
|
||||||
|
|
||||||
@item --assume-binary
|
|
||||||
@opindex assume-binary
|
|
||||||
Assume the input data is binary encoded.
|
|
||||||
|
|
||||||
@item --local-user @var{user_id}
|
|
||||||
@item -u @var{user_id}
|
|
||||||
@opindex local-user
|
|
||||||
@opindex -u
|
|
||||||
Set the user(s) to be used for signing. The default is the first
|
|
||||||
secret key found in the database.
|
|
||||||
|
|
||||||
@item --with-key-data
|
|
||||||
@opindex with-key-data
|
|
||||||
Displays extra information with the @code{--list-keys} commands. Especially
|
|
||||||
a line tagged @code{grp} is printed which tells you the keygrip of a
|
|
||||||
key. This string is for example used as the file name of the
|
|
||||||
secret key.
|
|
||||||
|
|
||||||
@item --with-validation
|
|
||||||
@opindex with-validation
|
|
||||||
When doing a key listing, do a full validation check for each key and
|
|
||||||
print the result. This is usually a slow operation because it
|
|
||||||
requires a CRL lookup and other operations.
|
|
||||||
|
|
||||||
@item --with-md5-fingerprint
|
|
||||||
For standard key listings, also print the MD5 fingerprint of the
|
|
||||||
certificate.
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@node CMS Options
|
|
||||||
@subsection How to change how the CMS is created.
|
|
||||||
|
|
||||||
@table @gnupgtabopt
|
|
||||||
@item --include-certs @var{n}
|
|
||||||
Using @var{n} of -2 includes all certificate except for the root cert,
|
|
||||||
-1 includes all certs, 0 does not include any certs, 1 includes only
|
|
||||||
the signers cert (this is the default) and all other positive
|
|
||||||
values include up to @var{n} certificates starting with the signer cert.
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@node Esoteric Options
|
|
||||||
@subsection Doing things one usually don't want todo.
|
|
||||||
|
|
||||||
|
|
||||||
@table @gnupgtabopt
|
|
||||||
|
|
||||||
@item --faked-system-time @var{epoch}
|
|
||||||
@opindex faked-system-time
|
|
||||||
This option is only useful for testing; it sets the system time back or
|
|
||||||
forth to @var{epoch} which is the number of seconds elapsed since the year
|
|
||||||
1970.
|
|
||||||
|
|
||||||
@item --debug-level @var{level}
|
|
||||||
@opindex debug-level
|
|
||||||
Select the debug level for investigating problems. @var{level} may be
|
|
||||||
one of:
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
@item none
|
|
||||||
no debugging at all.
|
|
||||||
@item basic
|
|
||||||
some basic debug messages
|
|
||||||
@item advanced
|
|
||||||
more verbose debug messages
|
|
||||||
@item expert
|
|
||||||
even more detailed messages
|
|
||||||
@item guru
|
|
||||||
all of the debug messages you can get
|
|
||||||
@end table
|
|
||||||
|
|
||||||
How these messages are mapped to the actual debugging flags is not
|
|
||||||
specified and may change with newer releaes of this program. They are
|
|
||||||
however carefully selected to best aid in debugging.
|
|
||||||
|
|
||||||
@item --debug @var{flags}
|
|
||||||
@opindex debug
|
|
||||||
This option is only useful for debugging and the behaviour may change
|
|
||||||
at any time without notice; using @code{--debug-levels} is the
|
|
||||||
preferred method to select the debug verbosity. FLAGS are bit encoded
|
|
||||||
and may be given in usual C-Syntax. The currently defined bits are:
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
@item 0 (1)
|
|
||||||
X.509 or OpenPGP protocol related data
|
|
||||||
@item 1 (2)
|
|
||||||
values of big number integers
|
|
||||||
@item 2 (4)
|
|
||||||
low level crypto operations
|
|
||||||
@item 5 (32)
|
|
||||||
memory allocation
|
|
||||||
@item 6 (64)
|
|
||||||
caching
|
|
||||||
@item 7 (128)
|
|
||||||
show memory statistics.
|
|
||||||
@item 9 (512)
|
|
||||||
write hashed data to files named @code{dbgmd-000*}
|
|
||||||
@item 10 (1024)
|
|
||||||
trace Assuan protocol
|
|
||||||
@end table
|
|
||||||
|
|
||||||
Note, that all flags set using this option may get overriden by
|
|
||||||
@code{--debug-level}.
|
|
||||||
|
|
||||||
@item --debug-all
|
|
||||||
@opindex debug-all
|
|
||||||
Same as @code{--debug=0xffffffff}
|
|
||||||
|
|
||||||
@item --debug-allow-core-dump
|
|
||||||
@opindex debug-allow-core-dump
|
|
||||||
Usually gpgsm tries to avoid dumping core by well written code and by
|
|
||||||
disabling core dumps for security reasons. However, bugs are pretty
|
|
||||||
durable beasts and to squash them it is sometimes useful to have a core
|
|
||||||
dump. This option enables core dumps unless the Bad Thing happened
|
|
||||||
before the option parsing.
|
|
||||||
|
|
||||||
@item --debug-no-chain-validation
|
|
||||||
@opindex debug-no-chain-validation
|
|
||||||
This is actually not a debugging option but only useful as such. It
|
|
||||||
lets gpgsm bypass all certificate chain validation checks.
|
|
||||||
|
|
||||||
@item --debug-ignore-expiration
|
|
||||||
@opindex debug-ignore-expiration
|
|
||||||
This is actually not a debugging option but only useful as such. It
|
|
||||||
lets gpgsm ignore all notAfter dates, this is used by the regresssion
|
|
||||||
tests.
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
All the long options may also be given in the configuration file after
|
|
||||||
stripping off the two leading dashes.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@c
|
|
||||||
@c Examples
|
|
||||||
@c
|
|
||||||
@node GPGSM Examples
|
|
||||||
@section Examples
|
|
||||||
|
|
||||||
@c man begin EXAMPLES
|
|
||||||
|
|
||||||
@example
|
|
||||||
$ gpgsm -er goo@@bar.net <plaintext >ciphertext
|
|
||||||
@end example
|
|
||||||
|
|
||||||
@c man end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@c ---------------------------------
|
|
||||||
@c The machine interface
|
|
||||||
@c --------------------------------
|
|
||||||
@node Unattended Usage
|
|
||||||
@section Unattended Usage
|
|
||||||
|
|
||||||
@sc{gpgsm} is often used as a backend engine by other software. To help
|
|
||||||
with this a machine interface has been defined to have an unambiguous
|
|
||||||
way to do this. This is most likely used with the @code{--server} command
|
|
||||||
but may also be used in the standard operation mode by using the
|
|
||||||
@code{--status-fd} option.
|
|
||||||
|
|
||||||
@menu
|
|
||||||
* Automated signature checking:: Automated signature checking.
|
|
||||||
@end menu
|
|
||||||
|
|
||||||
@node Automated signature checking,,,Unattended Usage
|
|
||||||
@section Automated signature checking
|
|
||||||
|
|
||||||
It is very important to understand the semantics used with signature
|
|
||||||
verification. Checking a signature is not as simple as it may sound and
|
|
||||||
so the ooperation si a bit complicated. In mosted cases it is required
|
|
||||||
to look at several status lines. Here is a table of all cases a signed
|
|
||||||
message may have:
|
|
||||||
|
|
||||||
@table @asis
|
|
||||||
@item The signature is valid
|
|
||||||
This does mean that the signature has been successfully verified, the
|
|
||||||
certificates are all sane. However there are two subcases with
|
|
||||||
important information: One of the certificates may have expired or a
|
|
||||||
signature of a message itself as expired. It is a sound practise to
|
|
||||||
consider such a signature still as valid but additional information
|
|
||||||
should be displayed. Depending on the subcase @sc{gpgsm} will issue
|
|
||||||
these status codes:
|
|
||||||
@table @asis
|
|
||||||
@item signature valid and nothing did expire
|
|
||||||
@code{GOODSIG}, @code{VALIDSIG}, @code{TRUST_FULLY}
|
|
||||||
@item signature valid but at least one certificate has expired
|
|
||||||
@code{EXPKEYSIG}, @code{VALIDSIG}, @code{TRUST_FULLY}
|
|
||||||
@item signature valid but expired
|
|
||||||
@code{EXPSIG}, @code{VALIDSIG}, @code{TRUST_FULLY}
|
|
||||||
Note, that this case is currently not implemented.
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@item The signature is invalid
|
|
||||||
This means that the signature verification failed (this is an indication
|
|
||||||
of af a transfer error, a programm error or tampering with the message).
|
|
||||||
@sc{gpgsm} issues one of these status codes sequences:
|
|
||||||
@table @code
|
|
||||||
@item @code{BADSIG}
|
|
||||||
@item @code{GOODSIG}, @code{VALIDSIG} @code{TRUST_NEVER}
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@item Error verifying a signature
|
|
||||||
For some reason the signature could not be verified, i.e. it can't be
|
|
||||||
decided whether the signature is valid or invalid. A common reason for
|
|
||||||
this is a missing certificate.
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
|
|
||||||
@c
|
|
||||||
@c Assuan Protocol
|
|
||||||
@c
|
|
||||||
@node GPGSM Protocol
|
|
||||||
@section The Protocol the Server Mode Uses.
|
|
||||||
|
|
||||||
Description of the protocol used to access GPGSM. GPGSM does implement
|
|
||||||
the Assuan protocol and in addition provides a regular command line
|
|
||||||
interface which exhibits a full client to this protocol (but uses
|
|
||||||
internal linking). To start gpgsm as a server the commandline "gpgsm
|
|
||||||
--server" must be used. Additional options are provided to select the
|
|
||||||
communication method (i.e. the name of the socket).
|
|
||||||
|
|
||||||
We assume that the connection has already been established; see the
|
|
||||||
Assuan manual for details.
|
|
||||||
|
|
||||||
@menu
|
|
||||||
* GPGSM ENCRYPT:: Encrypting a message.
|
|
||||||
* GPGSM DECRYPT:: Decrypting a message.
|
|
||||||
* GPGSM SIGN:: Signing a message.
|
|
||||||
* GPGSM VERIFY:: Verifying a message.
|
|
||||||
* GPGSM GENKEY:: Generating a key.
|
|
||||||
* GPGSM LISTKEYS:: List available keys.
|
|
||||||
* GPGSM EXPORT:: Export certificates.
|
|
||||||
* GPGSM IMPORT:: Import certificates.
|
|
||||||
* GPGSM DELETE:: Delete certificates.
|
|
||||||
@end menu
|
|
||||||
|
|
||||||
|
|
||||||
@node GPGSM ENCRYPT
|
|
||||||
@subsection Encrypting a Message
|
|
||||||
|
|
||||||
Before encrytion can be done the recipient must be set using the
|
|
||||||
command:
|
|
||||||
|
|
||||||
@example
|
|
||||||
RECIPIENT @var{userID}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Set the recipient for the encryption. @var{userID} should be the
|
|
||||||
internal representation of the key; the server may accept any other way
|
|
||||||
of specification. If this is a valid and trusted recipient the server
|
|
||||||
does respond with OK, otherwise the return is an ERR with the reason why
|
|
||||||
the recipient can't be used, the encryption will then not be done for
|
|
||||||
this recipient. If the policy is not to encrypt at all if not all
|
|
||||||
recipients are valid, the client has to take care of this. All
|
|
||||||
@code{RECIPIENT} commands are cumulative until a @code{RESET} or an
|
|
||||||
successful @code{ENCRYPT} command.
|
|
||||||
|
|
||||||
@example
|
|
||||||
INPUT FD=@var{n} [--armor|--base64|--binary]
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Set the file descriptor for the message to be encrypted to @var{n}.
|
|
||||||
Obviously the pipe must be open at that point, the server establishes
|
|
||||||
its own end. If the server returns an error the client should consider
|
|
||||||
this session failed.
|
|
||||||
|
|
||||||
The @code{--armor} option may be used to advice the server that the
|
|
||||||
input data is in @acronym{PEM} format, @code{--base64} advices that a
|
|
||||||
raw base-64 encoding is used, @code{--binary} advices of raw binary
|
|
||||||
input (@acronym{BER}). If none of these options is used, the server
|
|
||||||
tries to figure out the used encoding, but this may not always be
|
|
||||||
correct.
|
|
||||||
|
|
||||||
@example
|
|
||||||
OUTPUT FD=@var{n} [--armor|--base64]
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Set the file descriptor to be used for the output (i.e. the encrypted
|
|
||||||
message). Obviously the pipe must be open at that point, the server
|
|
||||||
establishes its own end. If the server returns an error he client
|
|
||||||
should consider this session failed.
|
|
||||||
|
|
||||||
The option armor encodes the output in @acronym{PEM} format, the
|
|
||||||
@code{--base64} option applies just a base 64 encoding. No option
|
|
||||||
creates binary output (@acronym{BER}).
|
|
||||||
|
|
||||||
The actual encryption is done using the command
|
|
||||||
|
|
||||||
@example
|
|
||||||
ENCRYPT
|
|
||||||
@end example
|
|
||||||
|
|
||||||
It takes the plaintext from the @code{INPUT} command, writes to the
|
|
||||||
ciphertext to the file descriptor set with the @code{OUTPUT} command,
|
|
||||||
take the recipients from all the recipients set so far. If this command
|
|
||||||
fails the clients should try to delete all output currently done or
|
|
||||||
otherwise mark it as invalid. GPGSM does ensure that there won't be any
|
|
||||||
security problem with leftover data on the output in this case.
|
|
||||||
|
|
||||||
This command should in general not fail, as all necessary checks have
|
|
||||||
been done while setting the recipients. The input and output pipes are
|
|
||||||
closed.
|
|
||||||
|
|
||||||
|
|
||||||
@node GPGSM DECRYPT
|
|
||||||
@subsection Decrypting a message
|
|
||||||
|
|
||||||
Input and output FDs are set the same way as in encryption, but
|
|
||||||
@code{INPUT} refers to the ciphertext and output to the plaintext. There
|
|
||||||
is no need to set recipients. GPGSM automatically strips any
|
|
||||||
@acronym{S/MIME} headers from the input, so it is valid to pass an
|
|
||||||
entire MIME part to the INPUT pipe.
|
|
||||||
|
|
||||||
The encryption is done by using the command
|
|
||||||
|
|
||||||
@example
|
|
||||||
DECRYPT
|
|
||||||
@end example
|
|
||||||
|
|
||||||
It performs the decrypt operation after doing some check on the internal
|
|
||||||
state. (e.g. that all needed data has been set). Because it utilizes
|
|
||||||
the GPG-Agent for the session key decryption, there is no need to ask
|
|
||||||
the client for a protecting passphrase - GpgAgent takes care of this by
|
|
||||||
requesting this from the user.
|
|
||||||
|
|
||||||
|
|
||||||
@node GPGSM SIGN
|
|
||||||
@subsection Signing a Message
|
|
||||||
|
|
||||||
Signing is usually done with these commands:
|
|
||||||
|
|
||||||
@example
|
|
||||||
INPUT FD=@var{n} [--armor|--base64|--binary]
|
|
||||||
@end example
|
|
||||||
|
|
||||||
This tells GPGSM to read the data to sign from file descriptor @var{n}.
|
|
||||||
|
|
||||||
@example
|
|
||||||
OUTPUT FD=@var{m} [--armor|--base64]
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Write the output to file descriptor @var{m}. If a detached signature is
|
|
||||||
requested, only the signature is written.
|
|
||||||
|
|
||||||
@example
|
|
||||||
SIGN [--detached]
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Sign the data set with the INPUT command and write it to the sink set by
|
|
||||||
OUTPUT. With @code{--detached}, a detached signature is created
|
|
||||||
(surprise).
|
|
||||||
|
|
||||||
The key used for signining is the default one or the one specified in
|
|
||||||
the configuration file. To get finer control over the keys, it is
|
|
||||||
possible to use the command
|
|
||||||
|
|
||||||
@example
|
|
||||||
SIGNER @var{userID}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
to the signer's key. @var{userID} should be the
|
|
||||||
internal representation of the key; the server may accept any other way
|
|
||||||
of specification. If this is a valid and trusted recipient the server
|
|
||||||
does respond with OK, otherwise the return is an ERR with the reason why
|
|
||||||
the key can't be used, the signature will then not be created using
|
|
||||||
this key. If the policy is not to sign at all if not all
|
|
||||||
keys are valid, the client has to take care of this. All
|
|
||||||
@code{SIGNER} commands are cumulative until a @code{RESET} is done.
|
|
||||||
Note that a @code{SIGN} does not reset this list of signers which is in
|
|
||||||
contrats to the @code{RECIPIENT} command.
|
|
||||||
|
|
||||||
|
|
||||||
@node GPGSM VERIFY
|
|
||||||
@subsection Verifying a Message
|
|
||||||
|
|
||||||
To verify a mesage the command:
|
|
||||||
|
|
||||||
@example
|
|
||||||
VERIFY
|
|
||||||
@end example
|
|
||||||
|
|
||||||
is used. It does a verify operation on the message send to the input FD.
|
|
||||||
The result is written out using status lines. If an output FD was
|
|
||||||
given, the signed text will be written to that. If the signature is a
|
|
||||||
detached one, the server will inquire about the signed material and the
|
|
||||||
client must provide it.
|
|
||||||
|
|
||||||
@node GPGSM GENKEY
|
|
||||||
@subsection Generating a Key
|
|
||||||
|
|
||||||
This is used to generate a new keypair, store the secret part in the
|
|
||||||
@acronym{PSE} and the public key in the key database. We will probably
|
|
||||||
add optional commands to allow the client to select whether a hardware
|
|
||||||
token is used to store the key. Configuration options to GPGSM can be
|
|
||||||
used to restrict the use of this command.
|
|
||||||
|
|
||||||
@example
|
|
||||||
GENKEY
|
|
||||||
@end example
|
|
||||||
|
|
||||||
GPGSM checks whether this command is allowed and then does an
|
|
||||||
INQUIRY to get the key parameters, the client should then send the
|
|
||||||
key parameters in the native format:
|
|
||||||
|
|
||||||
@example
|
|
||||||
S: INQUIRE KEY_PARAM native
|
|
||||||
C: D foo:fgfgfg
|
|
||||||
C: D bar
|
|
||||||
C: END
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Please note that the server may send Status info lines while reading the
|
|
||||||
data lines from the client. After this the key generation takes place
|
|
||||||
and the server eventually does send an ERR or OK response. Status lines
|
|
||||||
may be issued as a progress indicator.
|
|
||||||
|
|
||||||
|
|
||||||
@node GPGSM LISTKEYS
|
|
||||||
@subsection List available keys
|
|
||||||
|
|
||||||
To list the keys in the internal database or using an external key
|
|
||||||
provider, the command:
|
|
||||||
|
|
||||||
@example
|
|
||||||
LISTKEYS @var{pattern}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
is used. To allow multiple patterns (which are ORed during the search)
|
|
||||||
quoting is required: Spaces are to be translated into "+" or into "%20";
|
|
||||||
in turn this requires that the usual escape quoting rules are done.
|
|
||||||
|
|
||||||
@example
|
|
||||||
LISTSECRETKEYS @var{pattern}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Lists only the keys where a secret key is available.
|
|
||||||
|
|
||||||
The list commands commands are affected by the option
|
|
||||||
|
|
||||||
@example
|
|
||||||
OPTION list-mode=@var{mode}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
where mode may be:
|
|
||||||
@table @code
|
|
||||||
@item 0
|
|
||||||
Use default (which is usually the same as 1).
|
|
||||||
@item 1
|
|
||||||
List only the internal keys.
|
|
||||||
@item 2
|
|
||||||
List only the external keys.
|
|
||||||
@item 3
|
|
||||||
List internal and external keys.
|
|
||||||
@end table
|
|
||||||
|
|
||||||
Note that options are valid for the entire session.
|
|
||||||
|
|
||||||
|
|
||||||
@node GPGSM EXPORT
|
|
||||||
@subsection Export certificates
|
|
||||||
|
|
||||||
To export certificate from the internal key database the command:
|
|
||||||
|
|
||||||
@example
|
|
||||||
EXPORT @var{pattern}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
is used. To allow multiple patterns (which are ORed) quoting is
|
|
||||||
required: Spaces are to be translated into "+" or into "%20"; in turn
|
|
||||||
this requires that the usual escape quoting rules are done.
|
|
||||||
|
|
||||||
The format of the output depends on what was set with the OUTPUT
|
|
||||||
command. When using @acronym{PEM} encoding a few informational lines
|
|
||||||
are prepended.
|
|
||||||
|
|
||||||
|
|
||||||
@node GPGSM IMPORT
|
|
||||||
@subsection Import certificates
|
|
||||||
|
|
||||||
To import certificates into the internal key database, the command
|
|
||||||
|
|
||||||
@example
|
|
||||||
IMPORT
|
|
||||||
@end example
|
|
||||||
|
|
||||||
is used. The data is expected on the file descriptor set with the
|
|
||||||
@code{INPUT} command. Certain checks are performend on the
|
|
||||||
certificate. Note that the code will also handle PKCS\#12 files and
|
|
||||||
import private keys; a helper program is used for that.
|
|
||||||
|
|
||||||
|
|
||||||
@node GPGSM DELETE
|
|
||||||
@subsection Delete certificates
|
|
||||||
|
|
||||||
To delete certificate the command
|
|
||||||
|
|
||||||
@example
|
|
||||||
DELKEYS @var{pattern}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
is used. To allow multiple patterns (which are ORed) quoting is
|
|
||||||
required: Spaces are to be translated into "+" or into "%20"; in turn
|
|
||||||
this requires that the usual escape quoting rules are done.
|
|
||||||
|
|
||||||
The certificates must be specified unambiguously otherwise an error is
|
|
||||||
returned.
|
|
||||||
|
|
397
doc/gpl.texi
397
doc/gpl.texi
@ -1,397 +0,0 @@
|
|||||||
@node Copying
|
|
||||||
@appendix GNU GENERAL PUBLIC LICENSE
|
|
||||||
|
|
||||||
@cindex GPL, GNU General Public License
|
|
||||||
@center Version 2, June 1991
|
|
||||||
|
|
||||||
@display
|
|
||||||
Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc.
|
|
||||||
59 Temple Place -- Suite 330, Boston, MA 02111-1307, USA
|
|
||||||
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
@end display
|
|
||||||
|
|
||||||
@appendixsubsec Preamble
|
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
|
||||||
License is intended to guarantee your freedom to share and change free
|
|
||||||
software---to make sure the software is free for all its users. This
|
|
||||||
General Public License applies to most of the Free Software
|
|
||||||
Foundation's software and to any other program whose authors commit to
|
|
||||||
using it. (Some other Free Software Foundation software is covered by
|
|
||||||
the GNU Library General Public License instead.) You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
this service if you wish), that you receive source code or can get it
|
|
||||||
if you want it, that you can change the software or use pieces of it
|
|
||||||
in new free programs; and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
|
||||||
anyone to deny you these rights or to ask you to surrender the rights.
|
|
||||||
These restrictions translate to certain responsibilities for you if you
|
|
||||||
distribute copies of the software, or if you modify it.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must give the recipients all the rights that
|
|
||||||
you have. You must make sure that they, too, receive or can get the
|
|
||||||
source code. And you must show them these terms so they know their
|
|
||||||
rights.
|
|
||||||
|
|
||||||
We protect your rights with two steps: (1) copyright the software, and
|
|
||||||
(2) offer you this license which gives you legal permission to copy,
|
|
||||||
distribute and/or modify the software.
|
|
||||||
|
|
||||||
Also, for each author's protection and ours, we want to make certain
|
|
||||||
that everyone understands that there is no warranty for this free
|
|
||||||
software. If the software is modified by someone else and passed on, we
|
|
||||||
want its recipients to know that what they have is not the original, so
|
|
||||||
that any problems introduced by others will not reflect on the original
|
|
||||||
authors' reputations.
|
|
||||||
|
|
||||||
Finally, any free program is threatened constantly by software
|
|
||||||
patents. We wish to avoid the danger that redistributors of a free
|
|
||||||
program will individually obtain patent licenses, in effect making the
|
|
||||||
program proprietary. To prevent this, we have made it clear that any
|
|
||||||
patent must be licensed for everyone's free use or not licensed at all.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
@iftex
|
|
||||||
@appendixsubsec TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
@end iftex
|
|
||||||
@ifinfo
|
|
||||||
@center TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
@end ifinfo
|
|
||||||
|
|
||||||
@enumerate
|
|
||||||
@item
|
|
||||||
This License applies to any program or other work which contains
|
|
||||||
a notice placed by the copyright holder saying it may be distributed
|
|
||||||
under the terms of this General Public License. The ``Program'', below,
|
|
||||||
refers to any such program or work, and a ``work based on the Program''
|
|
||||||
means either the Program or any derivative work under copyright law:
|
|
||||||
that is to say, a work containing the Program or a portion of it,
|
|
||||||
either verbatim or with modifications and/or translated into another
|
|
||||||
language. (Hereinafter, translation is included without limitation in
|
|
||||||
the term ``modification''.) Each licensee is addressed as ``you''.
|
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running the Program is not restricted, and the output from the Program
|
|
||||||
is covered only if its contents constitute a work based on the
|
|
||||||
Program (independent of having been made by running the Program).
|
|
||||||
Whether that is true depends on what the Program does.
|
|
||||||
|
|
||||||
@item
|
|
||||||
You may copy and distribute verbatim copies of the Program's
|
|
||||||
source code as you receive it, in any medium, provided that you
|
|
||||||
conspicuously and appropriately publish on each copy an appropriate
|
|
||||||
copyright notice and disclaimer of warranty; keep intact all the
|
|
||||||
notices that refer to this License and to the absence of any warranty;
|
|
||||||
and give any other recipients of the Program a copy of this License
|
|
||||||
along with the Program.
|
|
||||||
|
|
||||||
You may charge a fee for the physical act of transferring a copy, and
|
|
||||||
you may at your option offer warranty protection in exchange for a fee.
|
|
||||||
|
|
||||||
@item
|
|
||||||
You may modify your copy or copies of the Program or any portion
|
|
||||||
of it, thus forming a work based on the Program, and copy and
|
|
||||||
distribute such modifications or work under the terms of Section 1
|
|
||||||
above, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
@enumerate a
|
|
||||||
@item
|
|
||||||
You must cause the modified files to carry prominent notices
|
|
||||||
stating that you changed the files and the date of any change.
|
|
||||||
|
|
||||||
@item
|
|
||||||
You must cause any work that you distribute or publish, that in
|
|
||||||
whole or in part contains or is derived from the Program or any
|
|
||||||
part thereof, to be licensed as a whole at no charge to all third
|
|
||||||
parties under the terms of this License.
|
|
||||||
|
|
||||||
@item
|
|
||||||
If the modified program normally reads commands interactively
|
|
||||||
when run, you must cause it, when started running for such
|
|
||||||
interactive use in the most ordinary way, to print or display an
|
|
||||||
announcement including an appropriate copyright notice and a
|
|
||||||
notice that there is no warranty (or else, saying that you provide
|
|
||||||
a warranty) and that users may redistribute the program under
|
|
||||||
these conditions, and telling the user how to view a copy of this
|
|
||||||
License. (Exception: if the Program itself is interactive but
|
|
||||||
does not normally print such an announcement, your work based on
|
|
||||||
the Program is not required to print an announcement.)
|
|
||||||
@end enumerate
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
|
||||||
identifiable sections of that work are not derived from the Program,
|
|
||||||
and can be reasonably considered independent and separate works in
|
|
||||||
themselves, then this License, and its terms, do not apply to those
|
|
||||||
sections when you distribute them as separate works. But when you
|
|
||||||
distribute the same sections as part of a whole which is a work based
|
|
||||||
on the Program, the distribution of the whole must be on the terms of
|
|
||||||
this License, whose permissions for other licensees extend to the
|
|
||||||
entire whole, and thus to each and every part regardless of who wrote it.
|
|
||||||
|
|
||||||
Thus, it is not the intent of this section to claim rights or contest
|
|
||||||
your rights to work written entirely by you; rather, the intent is to
|
|
||||||
exercise the right to control the distribution of derivative or
|
|
||||||
collective works based on the Program.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Program
|
|
||||||
with the Program (or with a work based on the Program) on a volume of
|
|
||||||
a storage or distribution medium does not bring the other work under
|
|
||||||
the scope of this License.
|
|
||||||
|
|
||||||
@item
|
|
||||||
You may copy and distribute the Program (or a work based on it,
|
|
||||||
under Section 2) in object code or executable form under the terms of
|
|
||||||
Sections 1 and 2 above provided that you also do one of the following:
|
|
||||||
|
|
||||||
@enumerate a
|
|
||||||
@item
|
|
||||||
Accompany it with the complete corresponding machine-readable
|
|
||||||
source code, which must be distributed under the terms of Sections
|
|
||||||
1 and 2 above on a medium customarily used for software interchange; or,
|
|
||||||
|
|
||||||
@item
|
|
||||||
Accompany it with a written offer, valid for at least three
|
|
||||||
years, to give any third party, for a charge no more than your
|
|
||||||
cost of physically performing source distribution, a complete
|
|
||||||
machine-readable copy of the corresponding source code, to be
|
|
||||||
distributed under the terms of Sections 1 and 2 above on a medium
|
|
||||||
customarily used for software interchange; or,
|
|
||||||
|
|
||||||
@item
|
|
||||||
Accompany it with the information you received as to the offer
|
|
||||||
to distribute corresponding source code. (This alternative is
|
|
||||||
allowed only for noncommercial distribution and only if you
|
|
||||||
received the program in object code or executable form with such
|
|
||||||
an offer, in accord with Subsection b above.)
|
|
||||||
@end enumerate
|
|
||||||
|
|
||||||
The source code for a work means the preferred form of the work for
|
|
||||||
making modifications to it. For an executable work, complete source
|
|
||||||
code means all the source code for all modules it contains, plus any
|
|
||||||
associated interface definition files, plus the scripts used to
|
|
||||||
control compilation and installation of the executable. However, as a
|
|
||||||
special exception, the source code distributed need not include
|
|
||||||
anything that is normally distributed (in either source or binary
|
|
||||||
form) with the major components (compiler, kernel, and so on) of the
|
|
||||||
operating system on which the executable runs, unless that component
|
|
||||||
itself accompanies the executable.
|
|
||||||
|
|
||||||
If distribution of executable or object code is made by offering
|
|
||||||
access to copy from a designated place, then offering equivalent
|
|
||||||
access to copy the source code from the same place counts as
|
|
||||||
distribution of the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
@item
|
|
||||||
You may not copy, modify, sublicense, or distribute the Program
|
|
||||||
except as expressly provided under this License. Any attempt
|
|
||||||
otherwise to copy, modify, sublicense or distribute the Program is
|
|
||||||
void, and will automatically terminate your rights under this License.
|
|
||||||
However, parties who have received copies, or rights, from you under
|
|
||||||
this License will not have their licenses terminated so long as such
|
|
||||||
parties remain in full compliance.
|
|
||||||
|
|
||||||
@item
|
|
||||||
You are not required to accept this License, since you have not
|
|
||||||
signed it. However, nothing else grants you permission to modify or
|
|
||||||
distribute the Program or its derivative works. These actions are
|
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
|
||||||
modifying or distributing the Program (or any work based on the
|
|
||||||
Program), you indicate your acceptance of this License to do so, and
|
|
||||||
all its terms and conditions for copying, distributing or modifying
|
|
||||||
the Program or works based on it.
|
|
||||||
|
|
||||||
@item
|
|
||||||
Each time you redistribute the Program (or any work based on the
|
|
||||||
Program), the recipient automatically receives a license from the
|
|
||||||
original licensor to copy, distribute or modify the Program subject to
|
|
||||||
these terms and conditions. You may not impose any further
|
|
||||||
restrictions on the recipients' exercise of the rights granted herein.
|
|
||||||
You are not responsible for enforcing compliance by third parties to
|
|
||||||
this License.
|
|
||||||
|
|
||||||
@item
|
|
||||||
If, as a consequence of a court judgment or allegation of patent
|
|
||||||
infringement or for any other reason (not limited to patent issues),
|
|
||||||
conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot
|
|
||||||
distribute so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you
|
|
||||||
may not distribute the Program at all. For example, if a patent
|
|
||||||
license would not permit royalty-free redistribution of the Program by
|
|
||||||
all those who receive copies directly or indirectly through you, then
|
|
||||||
the only way you could satisfy both it and this License would be to
|
|
||||||
refrain entirely from distribution of the Program.
|
|
||||||
|
|
||||||
If any portion of this section is held invalid or unenforceable under
|
|
||||||
any particular circumstance, the balance of the section is intended to
|
|
||||||
apply and the section as a whole is intended to apply in other
|
|
||||||
circumstances.
|
|
||||||
|
|
||||||
It is not the purpose of this section to induce you to infringe any
|
|
||||||
patents or other property right claims or to contest validity of any
|
|
||||||
such claims; this section has the sole purpose of protecting the
|
|
||||||
integrity of the free software distribution system, which is
|
|
||||||
implemented by public license practices. Many people have made
|
|
||||||
generous contributions to the wide range of software distributed
|
|
||||||
through that system in reliance on consistent application of that
|
|
||||||
system; it is up to the author/donor to decide if he or she is willing
|
|
||||||
to distribute software through any other system and a licensee cannot
|
|
||||||
impose that choice.
|
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
|
||||||
be a consequence of the rest of this License.
|
|
||||||
|
|
||||||
@item
|
|
||||||
If the distribution and/or use of the Program is restricted in
|
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
|
||||||
original copyright holder who places the Program under this License
|
|
||||||
may add an explicit geographical distribution limitation excluding
|
|
||||||
those countries, so that distribution is permitted only in or among
|
|
||||||
countries not thus excluded. In such case, this License incorporates
|
|
||||||
the limitation as if written in the body of this License.
|
|
||||||
|
|
||||||
@item
|
|
||||||
The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the Program
|
|
||||||
specifies a version number of this License which applies to it and ``any
|
|
||||||
later version'', you have the option of following the terms and conditions
|
|
||||||
either of that version or of any later version published by the Free
|
|
||||||
Software Foundation. If the Program does not specify a version number of
|
|
||||||
this License, you may choose any version ever published by the Free Software
|
|
||||||
Foundation.
|
|
||||||
|
|
||||||
@item
|
|
||||||
If you wish to incorporate parts of the Program into other free
|
|
||||||
programs whose distribution conditions are different, write to the author
|
|
||||||
to ask for permission. For software which is copyrighted by the Free
|
|
||||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
|
||||||
make exceptions for this. Our decision will be guided by the two goals
|
|
||||||
of preserving the free status of all derivatives of our free software and
|
|
||||||
of promoting the sharing and reuse of software generally.
|
|
||||||
|
|
||||||
@iftex
|
|
||||||
@heading NO WARRANTY
|
|
||||||
@end iftex
|
|
||||||
@ifinfo
|
|
||||||
@center NO WARRANTY
|
|
||||||
@end ifinfo
|
|
||||||
|
|
||||||
@item
|
|
||||||
BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
|
||||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
|
||||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
|
||||||
PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
|
||||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
|
||||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
|
||||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
|
||||||
REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
@item
|
|
||||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
|
||||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
|
||||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
|
||||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
|
||||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
|
||||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
|
||||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGES.
|
|
||||||
@end enumerate
|
|
||||||
|
|
||||||
@iftex
|
|
||||||
@heading END OF TERMS AND CONDITIONS
|
|
||||||
@end iftex
|
|
||||||
@ifinfo
|
|
||||||
@center END OF TERMS AND CONDITIONS
|
|
||||||
@end ifinfo
|
|
||||||
|
|
||||||
@page
|
|
||||||
@unnumberedsec How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
convey the exclusion of warranty; and each file should have at least
|
|
||||||
the ``copyright'' line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
@smallexample
|
|
||||||
@var{one line to give the program's name and an idea of what it does.}
|
|
||||||
Copyright (C) 19@var{yy} @var{name of author}
|
|
||||||
|
|
||||||
This program 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.
|
|
||||||
|
|
||||||
This program 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.
|
|
||||||
@end smallexample
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program is interactive, make it output a short notice like this
|
|
||||||
when it starts in an interactive mode:
|
|
||||||
|
|
||||||
@smallexample
|
|
||||||
Gnomovision version 69, Copyright (C) 19@var{yy} @var{name of author}
|
|
||||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
|
|
||||||
type `show w'. This is free software, and you are welcome
|
|
||||||
to redistribute it under certain conditions; type `show c'
|
|
||||||
for details.
|
|
||||||
@end smallexample
|
|
||||||
|
|
||||||
The hypothetical commands @samp{show w} and @samp{show c} should show
|
|
||||||
the appropriate parts of the General Public License. Of course, the
|
|
||||||
commands you use may be called something other than @samp{show w} and
|
|
||||||
@samp{show c}; they could even be mouse-clicks or menu items---whatever
|
|
||||||
suits your program.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
|
||||||
school, if any, to sign a ``copyright disclaimer'' for the program, if
|
|
||||||
necessary. Here is a sample; alter the names:
|
|
||||||
|
|
||||||
@smallexample
|
|
||||||
@group
|
|
||||||
Yoyodyne, Inc., hereby disclaims all copyright
|
|
||||||
interest in the program `Gnomovision'
|
|
||||||
(which makes passes at compilers) written
|
|
||||||
by James Hacker.
|
|
||||||
|
|
||||||
@var{signature of Ty Coon}, 1 April 1989
|
|
||||||
Ty Coon, President of Vice
|
|
||||||
@end group
|
|
||||||
@end smallexample
|
|
||||||
|
|
||||||
This General Public License does not permit incorporating your program into
|
|
||||||
proprietary programs. If your program is a subroutine library, you may
|
|
||||||
consider it more useful to permit linking proprietary applications with the
|
|
||||||
library. If this is what you want to do, use the GNU Library General
|
|
||||||
Public License instead of this License.
|
|
@ -1,387 +0,0 @@
|
|||||||
@c Copyright (C) 2002 Free Software Foundation, Inc.
|
|
||||||
@c This is part of the GnuPG manual.
|
|
||||||
@c For copying conditions, see the file gnupg.texi.
|
|
||||||
|
|
||||||
@node Invoking SCDAEMON
|
|
||||||
@chapter Invoking the SCDAEMON
|
|
||||||
@cindex SCDAEMON command options
|
|
||||||
@cindex command options
|
|
||||||
@cindex options, SCDAEMON command
|
|
||||||
|
|
||||||
@c man begin DESCRIPTION
|
|
||||||
|
|
||||||
The @sc{scdaeon} is a daemon to manage smartcards. It is usually
|
|
||||||
invoked by gpg-agent and in general not used directly.
|
|
||||||
|
|
||||||
@c man end
|
|
||||||
|
|
||||||
@xref{Option Index}, for an index to GPG-AGENTS's commands and options.
|
|
||||||
|
|
||||||
@menu
|
|
||||||
* Scdaemon Commands:: List of all commands.
|
|
||||||
* Scdaemon Options:: List of all options.
|
|
||||||
* Scdaemon Examples:: Some usage examples.
|
|
||||||
* Scdaemon Protocol:: The protocol the daemon uses.
|
|
||||||
@end menu
|
|
||||||
|
|
||||||
@c man begin COMMANDS
|
|
||||||
|
|
||||||
@node Scdaemon Commands
|
|
||||||
@section Commands
|
|
||||||
|
|
||||||
Commands are not distinguished from options execpt for the fact that
|
|
||||||
only one one command is allowed.
|
|
||||||
|
|
||||||
@table @gnupgtabopt
|
|
||||||
@item --version
|
|
||||||
@opindex version
|
|
||||||
Print the program version and licensing information. Not that you can
|
|
||||||
abbreviate this command.
|
|
||||||
|
|
||||||
@item --help, -h
|
|
||||||
@opindex help
|
|
||||||
Print a usage message summarizing the most usefule command-line options.
|
|
||||||
Not that you can abbreviate this command.
|
|
||||||
|
|
||||||
@item --dump-options
|
|
||||||
@opindex dump-options
|
|
||||||
Print a list of all available options and commands. Not that you can
|
|
||||||
abbreviate this command.
|
|
||||||
|
|
||||||
@item --server
|
|
||||||
@opindex server
|
|
||||||
Run in server mode and wait for commands on the @code{stdin}. This is
|
|
||||||
default mode is to create a socket and listen for commands there.
|
|
||||||
|
|
||||||
@item --daemon
|
|
||||||
@opindex daemon
|
|
||||||
Run the program in the background. This option is required to prevent
|
|
||||||
it from being accidently running in the background.
|
|
||||||
|
|
||||||
@item --print-atr
|
|
||||||
@opindex print-atr
|
|
||||||
This is mainly a debugging command, used to print the ATR
|
|
||||||
(Answer-To-Reset) of a card and exit immediately.
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
|
|
||||||
@c man begin OPTIONS
|
|
||||||
|
|
||||||
@node Scdaemon Options
|
|
||||||
@section Option Summary
|
|
||||||
|
|
||||||
@table @gnupgtabopt
|
|
||||||
|
|
||||||
@item --options @var{file}
|
|
||||||
@opindex options
|
|
||||||
Reads configuration from @var{file} instead of from the default
|
|
||||||
per-user configuration file. The default configuration file is named
|
|
||||||
@file{scdaemon.conf} and expected in the @file{.gnupg} directory directly
|
|
||||||
below the home directory of the user.
|
|
||||||
|
|
||||||
@item -v
|
|
||||||
@item --verbose
|
|
||||||
@opindex v
|
|
||||||
@opindex verbose
|
|
||||||
Outputs additional information while running.
|
|
||||||
You can increase the verbosity by giving several
|
|
||||||
verbose commands to @sc{gpgsm}, such as @samp{-vv}.
|
|
||||||
|
|
||||||
@item --debug-level @var{level}
|
|
||||||
@opindex debug-level
|
|
||||||
Select the debug level for investigating problems. @var{level} may be
|
|
||||||
one of:
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
@item none
|
|
||||||
no debugging at all.
|
|
||||||
@item basic
|
|
||||||
some basic debug messages
|
|
||||||
@item advanced
|
|
||||||
more verbose debug messages
|
|
||||||
@item expert
|
|
||||||
even more detailed messages
|
|
||||||
@item guru
|
|
||||||
all of the debug messages you can get
|
|
||||||
@end table
|
|
||||||
|
|
||||||
How these messages are mapped to the actual debugging flags is not
|
|
||||||
specified and may change with newer releaes of this program. They are
|
|
||||||
however carefully selected to best aid in debugging.
|
|
||||||
|
|
||||||
@item --debug @var{flags}
|
|
||||||
@opindex debug
|
|
||||||
This option is only useful for debugging and the behaviour may change at
|
|
||||||
any time without notice. FLAGS are bit encoded and may be given in
|
|
||||||
usual C-Syntax. The currently defined bits are:
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
@item 0 (1)
|
|
||||||
X.509 or OpenPGP protocol related data
|
|
||||||
@item 1 (2)
|
|
||||||
values of big number integers
|
|
||||||
@item 2 (4)
|
|
||||||
low level crypto operations
|
|
||||||
@item 5 (32)
|
|
||||||
memory allocation
|
|
||||||
@item 6 (64)
|
|
||||||
caching
|
|
||||||
@item 7 (128)
|
|
||||||
show memory statistics.
|
|
||||||
@item 9 (512)
|
|
||||||
write hashed data to files named @code{dbgmd-000*}
|
|
||||||
@item 10 (1024)
|
|
||||||
trace Assuan protocol
|
|
||||||
@item 12 (4096)
|
|
||||||
bypass all certificate validation
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@item --debug-all
|
|
||||||
@opindex debug-all
|
|
||||||
Same as @code{--debug=0xffffffff}
|
|
||||||
|
|
||||||
@item --debug-wait @var{n}
|
|
||||||
@opindex debug-wait
|
|
||||||
When running in server mode, wait @var{n} seconds before entering the
|
|
||||||
actual processing loop and print the pid. This gives time to attach a
|
|
||||||
debugger.
|
|
||||||
|
|
||||||
@item --debug-sc @var{n}
|
|
||||||
@opindex debug-sc
|
|
||||||
Set the debug level of the OpenSC library to @var{n}.
|
|
||||||
|
|
||||||
@item --no-detach
|
|
||||||
@opindex no-detach
|
|
||||||
Don't detach the process from the console. This is manly usefule for
|
|
||||||
debugging.
|
|
||||||
|
|
||||||
@item --log-file @var{file}
|
|
||||||
@opindex log-file
|
|
||||||
Append all logging output to @var{file}. This is very helpful in
|
|
||||||
seeing what the agent actually does.
|
|
||||||
|
|
||||||
@item --reader-port @var{number}
|
|
||||||
When the program has been build without OpenSC support, this option must
|
|
||||||
be used to specify the port of the card terminal. A value of 0 refers
|
|
||||||
to the first serial device; add 32768 to access USB devices. The
|
|
||||||
default is 32768 (first USB device).
|
|
||||||
|
|
||||||
@item --ctapi-driver @var{library}
|
|
||||||
Use @var{library} to access the smartcard reader. The current default
|
|
||||||
is @code{libtowitoko.so}.
|
|
||||||
|
|
||||||
|
|
||||||
@item --allow-admin
|
|
||||||
@itemx --deny-admin
|
|
||||||
@opindex allow-admin
|
|
||||||
@opindex deny-admin
|
|
||||||
This enables the use of Admin class commands for card application
|
|
||||||
where this is supported. Currently we support it for the OpenPGP
|
|
||||||
card. Deny is the default. This commands is useful to inhibit
|
|
||||||
accidental access to admin class command which could ultimately lock
|
|
||||||
the card through worng PIN numbers.
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
All the long options may also be given in the configuration file after
|
|
||||||
stripping off the two leading dashes.
|
|
||||||
|
|
||||||
|
|
||||||
@c
|
|
||||||
@c Examples
|
|
||||||
@c
|
|
||||||
@node Scdaemon Examples
|
|
||||||
@section Examples
|
|
||||||
|
|
||||||
@c man begin EXAMPLES
|
|
||||||
|
|
||||||
@example
|
|
||||||
$ scdaemon --server -v
|
|
||||||
@end example
|
|
||||||
|
|
||||||
@c man end
|
|
||||||
|
|
||||||
@c
|
|
||||||
@c Assuan Protocol
|
|
||||||
@c
|
|
||||||
@node Scdaemon Protocol
|
|
||||||
@section Scdaemon's Assuan Protocol
|
|
||||||
|
|
||||||
The SC-Daemon should be started by the system to provide access to
|
|
||||||
external tokens. Using Smartcards on a multi-user system does not
|
|
||||||
make much sense expcet for system services, but in this case no
|
|
||||||
regular user accounts are hosted on the machine.
|
|
||||||
|
|
||||||
A client connects to the SC-Daemon by connecting to the socket named
|
|
||||||
@file{/var/run/scdaemon/socket}, configuration information is read from
|
|
||||||
@var{/etc/scdaemon.conf}
|
|
||||||
|
|
||||||
Each connection acts as one session, SC-Daemon takes care of
|
|
||||||
syncronizing access to a token between sessions.
|
|
||||||
|
|
||||||
@menu
|
|
||||||
* Scdaemon SERIALNO:: Return the serial number.
|
|
||||||
* Scdaemon LEARN:: Read all useful information from the card.
|
|
||||||
* Scdaemon READCERT:: Return a certificate.
|
|
||||||
* Scdaemon READKEY:: Return a public key.
|
|
||||||
* Scdaemon PKSIGN:: Signing data with a Smartcard.
|
|
||||||
* Scdaemon PKDECRYPT:: Decrypting data with a Smartcard.
|
|
||||||
* Scdaemon GETATTR:: Read an attribute's value.
|
|
||||||
* Scdaemon SETATTR:: Update an attribute's value.
|
|
||||||
* Scdaemon GENKEY:: Generate a new key on-card.
|
|
||||||
* Scdaemon RANDOM:: Return random bytes generate on-card.
|
|
||||||
* Scdaemon PASSWD:: Change PINs.
|
|
||||||
* Scdaemon CHECKPIN:: Perform a VERIFY operation.
|
|
||||||
@end menu
|
|
||||||
|
|
||||||
@node Scdaemon SERIALNO
|
|
||||||
@subsection Return the serial number
|
|
||||||
|
|
||||||
This command should be used to check for the presence of a card. It is
|
|
||||||
special in that it can be used to reset the card. Most other commands
|
|
||||||
will return an error when a card change has been detected and the use of
|
|
||||||
this function is therefore required.
|
|
||||||
|
|
||||||
Background: We want to keep the client clear of handling card changes
|
|
||||||
between operations; i.e. the client can assume that all operations are
|
|
||||||
done on the same card unless he call this function.
|
|
||||||
|
|
||||||
@example
|
|
||||||
SERIALNO
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Return the serial number of the card using a status reponse like:
|
|
||||||
|
|
||||||
@example
|
|
||||||
S SERIALNO D27600000000000000000000 0
|
|
||||||
@end example
|
|
||||||
|
|
||||||
The trailing 0 should be ignored for now, it is reserved for a future
|
|
||||||
extension. The serial number is the hex encoded value identified by
|
|
||||||
the @code{0x5A} tag in the GDO file (FIX=0x2F02).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@node Scdaemon LEARN
|
|
||||||
@subsection Read all useful information from the card
|
|
||||||
|
|
||||||
@example
|
|
||||||
LEARN [--force]
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Learn all useful information of the currently inserted card. When
|
|
||||||
used without the force options, the command might do an INQUIRE
|
|
||||||
like this:
|
|
||||||
|
|
||||||
@example
|
|
||||||
INQUIRE KNOWNCARDP <hexstring_with_serialNumber> <timestamp>
|
|
||||||
@end example
|
|
||||||
|
|
||||||
The client should just send an @code{END} if the processing should go on
|
|
||||||
or a @code{CANCEL} to force the function to terminate with a cancel
|
|
||||||
error message. The response of this command is a list of status lines
|
|
||||||
formatted as this:
|
|
||||||
|
|
||||||
@example
|
|
||||||
S KEYPAIRINFO @var{hexstring_with_keygrip} @var{hexstring_with_id}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
If there is no certificate yet stored on the card a single "X" is
|
|
||||||
returned in @var{hexstring_with_keygrip}.
|
|
||||||
|
|
||||||
@node Scdaemon READCERT
|
|
||||||
@subsection Return a certificate
|
|
||||||
|
|
||||||
@example
|
|
||||||
READCERT @var{hexified_certid}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
This function is used to read a certificate identified by
|
|
||||||
@var{hexified_certid} from the card.
|
|
||||||
|
|
||||||
|
|
||||||
@node Scdaemon READKEY
|
|
||||||
@subsection Return a public key
|
|
||||||
|
|
||||||
@example
|
|
||||||
READKEY @var{hexified_certid}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Return the public key for the given cert or key ID as an standard
|
|
||||||
S-Expression.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@node Scdaemon PKSIGN
|
|
||||||
@subsection Signing data with a Smartcard
|
|
||||||
|
|
||||||
To sign some data the caller should use the command
|
|
||||||
|
|
||||||
@example
|
|
||||||
SETDATA @var{hexstring}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
to tell scdaemon about the data to be signed. The data must be given in
|
|
||||||
hex notation. The actual signing is done using the command
|
|
||||||
|
|
||||||
@example
|
|
||||||
PKSIGN @var{keyid}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
where @var{keyid} is the hexified ID of the key to be used. The key id
|
|
||||||
may have been retrieved using the command @code{LEARN}.
|
|
||||||
|
|
||||||
|
|
||||||
@node Scdaemon PKDECRYPT
|
|
||||||
@subsection Decrypting data with a Smartcard
|
|
||||||
|
|
||||||
To decrypt some data the caller should use the command
|
|
||||||
|
|
||||||
@example
|
|
||||||
SETDATA @var{hexstring}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
to tell scdaemon about the data to be decrypted. The data must be given in
|
|
||||||
hex notation. The actual decryption is then done using the command
|
|
||||||
|
|
||||||
@example
|
|
||||||
PKDECRYPT @var{keyid}
|
|
||||||
@end example
|
|
||||||
|
|
||||||
where @var{keyid} is the hexified ID of the key to be used.
|
|
||||||
|
|
||||||
|
|
||||||
@node Scdaemon GETATTR
|
|
||||||
@subsection Read an attribute's value.
|
|
||||||
|
|
||||||
TO BE WRITTEN.
|
|
||||||
|
|
||||||
@node Scdaemon SETATTR
|
|
||||||
@subsection Update an attribute's value.
|
|
||||||
|
|
||||||
TO BE WRITTEN.
|
|
||||||
|
|
||||||
@node Scdaemon GENKEY
|
|
||||||
@subsection Generate a new key on-card.
|
|
||||||
|
|
||||||
TO BE WRITTEN.
|
|
||||||
|
|
||||||
@node Scdaemon RANDOM
|
|
||||||
@subsection Return random bytes generate on-card.
|
|
||||||
|
|
||||||
TO BE WRITTEN.
|
|
||||||
|
|
||||||
|
|
||||||
@node Scdaemon PASSWD
|
|
||||||
@subsection Change PINs.
|
|
||||||
|
|
||||||
TO BE WRITTEN.
|
|
||||||
|
|
||||||
|
|
||||||
@node Scdaemon CHECKPIN
|
|
||||||
@subsection Perform a VERIFY operation.
|
|
||||||
|
|
||||||
TO BE WRITTEN.
|
|
||||||
|
|
||||||
|
|
8948
g10/ChangeLog
8948
g10/ChangeLog
File diff suppressed because it is too large
Load Diff
121
g10/Makefile.am
121
g10/Makefile.am
@ -1,121 +0,0 @@
|
|||||||
# Copyright (C) 1998, 1999, 2000, 2001, 2002,
|
|
||||||
# 2003 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
|
|
||||||
|
|
||||||
## Process this file with automake to produce Makefile.in
|
|
||||||
|
|
||||||
EXTRA_DIST = options.skel
|
|
||||||
|
|
||||||
AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/include \
|
|
||||||
-I$(top_srcdir)/intl
|
|
||||||
|
|
||||||
include $(top_srcdir)/am/cmacros.am
|
|
||||||
|
|
||||||
AM_CFLAGS = $(LIBGCRYPT_CFLAGS)
|
|
||||||
|
|
||||||
needed_libs = ../common/libcommon.a ../jnlib/libjnlib.a
|
|
||||||
|
|
||||||
bin_PROGRAMS = gpg2 gpgv2
|
|
||||||
|
|
||||||
common_source = \
|
|
||||||
global.h gpg.h \
|
|
||||||
build-packet.c \
|
|
||||||
compress.c \
|
|
||||||
filter.h \
|
|
||||||
free-packet.c \
|
|
||||||
getkey.c \
|
|
||||||
keydb.c keydb.h \
|
|
||||||
keyring.c keyring.h \
|
|
||||||
seskey.c \
|
|
||||||
kbnode.c \
|
|
||||||
main.h \
|
|
||||||
mainproc.c \
|
|
||||||
armor.c \
|
|
||||||
mdfilter.c \
|
|
||||||
textfilter.c \
|
|
||||||
progress.c \
|
|
||||||
misc.c \
|
|
||||||
options.h \
|
|
||||||
openfile.c \
|
|
||||||
keyid.c \
|
|
||||||
packet.h \
|
|
||||||
parse-packet.c \
|
|
||||||
comment.c \
|
|
||||||
status.c \
|
|
||||||
status.h \
|
|
||||||
plaintext.c \
|
|
||||||
sig-check.c \
|
|
||||||
keylist.c \
|
|
||||||
pkglue.c pkglue.h
|
|
||||||
|
|
||||||
gpg2_SOURCES = g10.c \
|
|
||||||
$(common_source) \
|
|
||||||
pkclist.c \
|
|
||||||
skclist.c \
|
|
||||||
pubkey-enc.c \
|
|
||||||
passphrase.c \
|
|
||||||
seckey-cert.c \
|
|
||||||
encr-data.c \
|
|
||||||
cipher.c \
|
|
||||||
encode.c \
|
|
||||||
sign.c \
|
|
||||||
verify.c \
|
|
||||||
revoke.c \
|
|
||||||
decrypt.c \
|
|
||||||
keyedit.c \
|
|
||||||
dearmor.c \
|
|
||||||
import.c \
|
|
||||||
export.c \
|
|
||||||
trustdb.c \
|
|
||||||
trustdb.h \
|
|
||||||
tdbdump.c \
|
|
||||||
tdbio.c \
|
|
||||||
tdbio.h \
|
|
||||||
delkey.c \
|
|
||||||
keygen.c \
|
|
||||||
pipemode.c \
|
|
||||||
helptext.c \
|
|
||||||
keyserver.c \
|
|
||||||
keyserver-internal.h \
|
|
||||||
photoid.c photoid.h \
|
|
||||||
call-agent.c call-agent.h \
|
|
||||||
card-util.c \
|
|
||||||
exec.c exec.h
|
|
||||||
|
|
||||||
gpgv2_SOURCES = gpgv.c \
|
|
||||||
$(common_source) \
|
|
||||||
verify.c
|
|
||||||
|
|
||||||
#gpgd_SOURCES = gpgd.c \
|
|
||||||
# ks-proto.h \
|
|
||||||
# ks-proto.c \
|
|
||||||
# ks-db.c \
|
|
||||||
# ks-db.h \
|
|
||||||
# $(common_source)
|
|
||||||
|
|
||||||
LDADD = $(needed_libs) @INTLLIBS@ @CAPLIBS@ @ZLIBS@ @W32LIBS@
|
|
||||||
gpg2_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error
|
|
||||||
gpgv2_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error
|
|
||||||
|
|
||||||
$(PROGRAMS): $(needed_libs)
|
|
||||||
|
|
||||||
install-data-local:
|
|
||||||
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
|
|
||||||
$(INSTALL_DATA) $(srcdir)/options.skel \
|
|
||||||
$(DESTDIR)$(pkgdatadir)/options.skel
|
|
||||||
|
|
24
g10/OPTIONS
24
g10/OPTIONS
@ -1,24 +0,0 @@
|
|||||||
# Some notes used by the maintainers
|
|
||||||
|
|
||||||
|
|
||||||
store
|
|
||||||
# simply packs the input data into a rfc1991 packet format
|
|
||||||
|
|
||||||
check-trustdb
|
|
||||||
|
|
||||||
|
|
||||||
compress-keys
|
|
||||||
# compress exported key, compress level is still set with "-z" and
|
|
||||||
# algorithm with --compress-algo" - Default is to not compress keys, as
|
|
||||||
# this is better for interoperability.
|
|
||||||
|
|
||||||
compress-sigs
|
|
||||||
# Normally, compressing of signatures does not make sense; so this
|
|
||||||
# is disabled for detached signatures unless this option is used.
|
|
||||||
|
|
||||||
run-as-shm-coprocess [request-locked-shm-size]
|
|
||||||
# very special :-)
|
|
||||||
# You will have to use "--status-fd" too
|
|
||||||
# Note: This option does only work if given on the command line.
|
|
||||||
|
|
||||||
|
|
1334
g10/armor.c
1334
g10/armor.c
File diff suppressed because it is too large
Load Diff
1203
g10/build-packet.c
1203
g10/build-packet.c
File diff suppressed because it is too large
Load Diff
893
g10/call-agent.c
893
g10/call-agent.c
@ -1,893 +0,0 @@
|
|||||||
/* call-agent.c - divert operations to the agent
|
|
||||||
* Copyright (C) 2001, 2002, 2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if 0 /* lety Emacs display a red warning */
|
|
||||||
#error fixme: this shares a lof of code with the file in ../sm
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#ifdef HAVE_LOCALE_H
|
|
||||||
#include <locale.h>
|
|
||||||
#endif
|
|
||||||
#include <assuan.h>
|
|
||||||
|
|
||||||
#include "gpg.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "membuf.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "i18n.h"
|
|
||||||
#include "call-agent.h"
|
|
||||||
|
|
||||||
#ifndef DBG_ASSUAN
|
|
||||||
# define DBG_ASSUAN 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static ASSUAN_CONTEXT agent_ctx = NULL;
|
|
||||||
static int force_pipe_server = 1; /* FIXME: set this back to 0. */
|
|
||||||
|
|
||||||
struct cipher_parm_s {
|
|
||||||
ASSUAN_CONTEXT ctx;
|
|
||||||
const char *ciphertext;
|
|
||||||
size_t ciphertextlen;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct genkey_parm_s {
|
|
||||||
ASSUAN_CONTEXT ctx;
|
|
||||||
const char *sexp;
|
|
||||||
size_t sexplen;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Try to connect to the agent via socket or fork it off and work by
|
|
||||||
pipes. Handle the server's initial greeting */
|
|
||||||
static int
|
|
||||||
start_agent (void)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
char *infostr, *p;
|
|
||||||
ASSUAN_CONTEXT ctx;
|
|
||||||
char *dft_display = NULL;
|
|
||||||
char *dft_ttyname = NULL;
|
|
||||||
char *dft_ttytype = NULL;
|
|
||||||
char *old_lc = NULL;
|
|
||||||
char *dft_lc = NULL;
|
|
||||||
|
|
||||||
if (agent_ctx)
|
|
||||||
return 0; /* fixme: We need a context for each thread or serialize
|
|
||||||
the access to the agent. */
|
|
||||||
|
|
||||||
infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO");
|
|
||||||
if (!infostr || !*infostr)
|
|
||||||
{
|
|
||||||
const char *pgmname;
|
|
||||||
const char *argv[3];
|
|
||||||
int no_close_list[3];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (opt.verbose)
|
|
||||||
log_info (_("no running gpg-agent - starting one\n"));
|
|
||||||
|
|
||||||
if (fflush (NULL))
|
|
||||||
{
|
|
||||||
gpg_error_t tmperr = gpg_error_from_errno (errno);
|
|
||||||
log_error ("error flushing pending output: %s\n", strerror (errno));
|
|
||||||
return tmperr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!opt.agent_program || !*opt.agent_program)
|
|
||||||
opt.agent_program = GNUPG_DEFAULT_AGENT;
|
|
||||||
if ( !(pgmname = strrchr (opt.agent_program, '/')))
|
|
||||||
pgmname = opt.agent_program;
|
|
||||||
else
|
|
||||||
pgmname++;
|
|
||||||
|
|
||||||
argv[0] = pgmname;
|
|
||||||
argv[1] = "--server";
|
|
||||||
argv[2] = NULL;
|
|
||||||
|
|
||||||
i=0;
|
|
||||||
if (log_get_fd () != -1)
|
|
||||||
no_close_list[i++] = log_get_fd ();
|
|
||||||
no_close_list[i++] = fileno (stderr);
|
|
||||||
no_close_list[i] = -1;
|
|
||||||
|
|
||||||
/* connect to the agent and perform initial handshaking */
|
|
||||||
rc = assuan_pipe_connect (&ctx, opt.agent_program, (char**)argv,
|
|
||||||
no_close_list);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int prot;
|
|
||||||
int pid;
|
|
||||||
|
|
||||||
infostr = xstrdup (infostr);
|
|
||||||
if ( !(p = strchr (infostr, ':')) || p == infostr)
|
|
||||||
{
|
|
||||||
log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
|
|
||||||
xfree (infostr);
|
|
||||||
force_pipe_server = 1;
|
|
||||||
return start_agent ();
|
|
||||||
}
|
|
||||||
*p++ = 0;
|
|
||||||
pid = atoi (p);
|
|
||||||
while (*p && *p != ':')
|
|
||||||
p++;
|
|
||||||
prot = *p? atoi (p+1) : 0;
|
|
||||||
if (prot != 1)
|
|
||||||
{
|
|
||||||
log_error (_("gpg-agent protocol version %d is not supported\n"),
|
|
||||||
prot);
|
|
||||||
xfree (infostr);
|
|
||||||
force_pipe_server = 1;
|
|
||||||
return start_agent ();
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = assuan_socket_connect (&ctx, infostr, pid);
|
|
||||||
xfree (infostr);
|
|
||||||
if (rc == ASSUAN_Connect_Failed)
|
|
||||||
{
|
|
||||||
log_error (_("can't connect to the agent - trying fall back\n"));
|
|
||||||
force_pipe_server = 1;
|
|
||||||
return start_agent ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
log_error ("can't connect to the agent: %s\n", assuan_strerror (rc));
|
|
||||||
return gpg_error (GPG_ERR_NO_AGENT);
|
|
||||||
}
|
|
||||||
agent_ctx = ctx;
|
|
||||||
|
|
||||||
if (DBG_ASSUAN)
|
|
||||||
log_debug ("connection to agent established\n");
|
|
||||||
|
|
||||||
rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
|
|
||||||
if (rc)
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
|
|
||||||
dft_display = getenv ("DISPLAY");
|
|
||||||
if (opt.display || dft_display)
|
|
||||||
{
|
|
||||||
char *optstr;
|
|
||||||
if (asprintf (&optstr, "OPTION display=%s",
|
|
||||||
opt.display ? opt.display : dft_display) < 0)
|
|
||||||
return gpg_error_from_errno (errno);
|
|
||||||
rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
NULL);
|
|
||||||
free (optstr);
|
|
||||||
if (rc)
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
if (!opt.ttyname)
|
|
||||||
{
|
|
||||||
dft_ttyname = getenv ("GPG_TTY");
|
|
||||||
if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
|
|
||||||
dft_ttyname = ttyname (0);
|
|
||||||
}
|
|
||||||
if (opt.ttyname || dft_ttyname)
|
|
||||||
{
|
|
||||||
char *optstr;
|
|
||||||
if (asprintf (&optstr, "OPTION ttyname=%s",
|
|
||||||
opt.ttyname ? opt.ttyname : dft_ttyname) < 0)
|
|
||||||
return gpg_error_from_errno (errno);
|
|
||||||
rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
NULL);
|
|
||||||
free (optstr);
|
|
||||||
if (rc)
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
dft_ttytype = getenv ("TERM");
|
|
||||||
if (opt.ttytype || (dft_ttyname && dft_ttytype))
|
|
||||||
{
|
|
||||||
char *optstr;
|
|
||||||
if (asprintf (&optstr, "OPTION ttytype=%s",
|
|
||||||
opt.ttyname ? opt.ttytype : dft_ttytype) < 0)
|
|
||||||
return gpg_error_from_errno (errno);
|
|
||||||
rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
NULL);
|
|
||||||
free (optstr);
|
|
||||||
if (rc)
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
|
|
||||||
old_lc = setlocale (LC_CTYPE, NULL);
|
|
||||||
if (old_lc)
|
|
||||||
{
|
|
||||||
old_lc = strdup (old_lc);
|
|
||||||
if (!old_lc)
|
|
||||||
return gpg_error_from_errno (errno);
|
|
||||||
|
|
||||||
}
|
|
||||||
dft_lc = setlocale (LC_CTYPE, "");
|
|
||||||
#endif
|
|
||||||
if (opt.lc_ctype || (dft_ttyname && dft_lc))
|
|
||||||
{
|
|
||||||
char *optstr;
|
|
||||||
if (asprintf (&optstr, "OPTION lc-ctype=%s",
|
|
||||||
opt.lc_ctype ? opt.lc_ctype : dft_lc) < 0)
|
|
||||||
rc = gpg_error_from_errno (errno);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
NULL);
|
|
||||||
free (optstr);
|
|
||||||
if (rc)
|
|
||||||
rc = map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
|
|
||||||
if (old_lc)
|
|
||||||
{
|
|
||||||
setlocale (LC_CTYPE, old_lc);
|
|
||||||
free (old_lc);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
|
|
||||||
old_lc = setlocale (LC_MESSAGES, NULL);
|
|
||||||
if (old_lc)
|
|
||||||
{
|
|
||||||
old_lc = strdup (old_lc);
|
|
||||||
if (!old_lc)
|
|
||||||
return gpg_error_from_errno (errno);
|
|
||||||
}
|
|
||||||
dft_lc = setlocale (LC_MESSAGES, "");
|
|
||||||
#endif
|
|
||||||
if (opt.lc_messages || (dft_ttyname && dft_lc))
|
|
||||||
{
|
|
||||||
char *optstr;
|
|
||||||
if (asprintf (&optstr, "OPTION lc-messages=%s",
|
|
||||||
opt.lc_messages ? opt.lc_messages : dft_lc) < 0)
|
|
||||||
rc = gpg_error_from_errno (errno);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
NULL);
|
|
||||||
free (optstr);
|
|
||||||
if (rc)
|
|
||||||
rc = map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
|
|
||||||
if (old_lc)
|
|
||||||
{
|
|
||||||
setlocale (LC_MESSAGES, old_lc);
|
|
||||||
free (old_lc);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Return a new malloced string by unescaping the string S. Escaping
|
|
||||||
is percent escaping and '+'/space mapping. A binary nul will
|
|
||||||
silently be replaced by a 0xFF. Function returns NULL to indicate
|
|
||||||
an out of memory status. */
|
|
||||||
static char *
|
|
||||||
unescape_status_string (const unsigned char *s)
|
|
||||||
{
|
|
||||||
char *buffer, *d;
|
|
||||||
|
|
||||||
buffer = d = xtrymalloc (strlen (s)+1);
|
|
||||||
if (!buffer)
|
|
||||||
return NULL;
|
|
||||||
while (*s)
|
|
||||||
{
|
|
||||||
if (*s == '%' && s[1] && s[2])
|
|
||||||
{
|
|
||||||
s++;
|
|
||||||
*d = xtoi_2 (s);
|
|
||||||
if (!*d)
|
|
||||||
*d = '\xff';
|
|
||||||
d++;
|
|
||||||
s += 2;
|
|
||||||
}
|
|
||||||
else if (*s == '+')
|
|
||||||
{
|
|
||||||
*d++ = ' ';
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*d++ = *s++;
|
|
||||||
}
|
|
||||||
*d = 0;
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Take a 20 byte hexencoded string and put it into the the provided
|
|
||||||
20 byte buffer FPR in binary format. */
|
|
||||||
static int
|
|
||||||
unhexify_fpr (const char *hexstr, unsigned char *fpr)
|
|
||||||
{
|
|
||||||
const char *s;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
for (s=hexstr, n=0; hexdigitp (s); s++, n++)
|
|
||||||
;
|
|
||||||
if (*s || (n != 40))
|
|
||||||
return 0; /* no fingerprint (invalid or wrong length). */
|
|
||||||
n /= 2;
|
|
||||||
for (s=hexstr, n=0; *s; s += 2, n++)
|
|
||||||
fpr[n] = xtoi_2 (s);
|
|
||||||
return 1; /* okay */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Take the serial number from LINE and return it verbatim in a newly
|
|
||||||
allocated string. We make sure that only hex characters are
|
|
||||||
returned. */
|
|
||||||
static char *
|
|
||||||
store_serialno (const char *line)
|
|
||||||
{
|
|
||||||
const char *s;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
for (s=line; hexdigitp (s); s++)
|
|
||||||
;
|
|
||||||
p = xtrymalloc (s + 1 - line);
|
|
||||||
if (p)
|
|
||||||
{
|
|
||||||
memcpy (p, line, s-line);
|
|
||||||
p[s-line] = 0;
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Handle a KEYPARMS inquiry. Note, we only send the data,
|
|
||||||
assuan_transact takes care of flushing and writing the end */
|
|
||||||
static AssuanError
|
|
||||||
inq_genkey_parms (void *opaque, const char *keyword)
|
|
||||||
{
|
|
||||||
struct genkey_parm_s *parm = opaque;
|
|
||||||
AssuanError rc;
|
|
||||||
|
|
||||||
rc = assuan_send_data (parm->ctx, parm->sexp, parm->sexplen);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Call the agent to generate a new key */
|
|
||||||
int
|
|
||||||
agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
struct genkey_parm_s gk_parm;
|
|
||||||
membuf_t data;
|
|
||||||
size_t len;
|
|
||||||
char *buf;
|
|
||||||
|
|
||||||
*r_pubkey = NULL;
|
|
||||||
rc = start_agent ();
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
rc = assuan_transact (agent_ctx, "RESET", NULL, NULL,
|
|
||||||
NULL, NULL, NULL, NULL);
|
|
||||||
if (rc)
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
|
|
||||||
init_membuf (&data, 1024);
|
|
||||||
gk_parm.ctx = agent_ctx;
|
|
||||||
gk_parm.sexp = keyparms;
|
|
||||||
gk_parm.sexplen = gcry_sexp_canon_len (keyparms, 0, NULL, NULL);
|
|
||||||
if (!gk_parm.sexplen)
|
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
|
||||||
rc = assuan_transact (agent_ctx, "GENKEY",
|
|
||||||
membuf_data_cb, &data,
|
|
||||||
inq_genkey_parms, &gk_parm, NULL, NULL);
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
xfree (get_membuf (&data, &len));
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
buf = get_membuf (&data, &len);
|
|
||||||
if (!buf)
|
|
||||||
return gpg_error (GPG_ERR_ENOMEM);
|
|
||||||
if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
|
|
||||||
{
|
|
||||||
xfree (buf);
|
|
||||||
return gpg_error (GPG_ERR_INV_SEXP);
|
|
||||||
}
|
|
||||||
*r_pubkey = buf;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /*0*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Ask the agent whether the corresponding secret key is available for
|
|
||||||
the given keygrip. */
|
|
||||||
int
|
|
||||||
agent_havekey (const char *hexkeygrip)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
char line[ASSUAN_LINELENGTH];
|
|
||||||
|
|
||||||
rc = start_agent ();
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
if (!hexkeygrip || strlen (hexkeygrip) != 40)
|
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
|
||||||
|
|
||||||
snprintf (line, DIM(line)-1, "HAVEKEY %s", hexkeygrip);
|
|
||||||
line[DIM(line)-1] = 0;
|
|
||||||
|
|
||||||
rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Release the card info structure INFO. */
|
|
||||||
void
|
|
||||||
agent_release_card_info (struct agent_card_info_s *info)
|
|
||||||
{
|
|
||||||
if (!info)
|
|
||||||
return;
|
|
||||||
|
|
||||||
xfree (info->serialno); info->serialno = NULL;
|
|
||||||
xfree (info->disp_name); info->disp_name = NULL;
|
|
||||||
xfree (info->disp_lang); info->disp_lang = NULL;
|
|
||||||
xfree (info->pubkey_url); info->pubkey_url = NULL;
|
|
||||||
xfree (info->login_data); info->login_data = NULL;
|
|
||||||
info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static AssuanError
|
|
||||||
learn_status_cb (void *opaque, const char *line)
|
|
||||||
{
|
|
||||||
struct agent_card_info_s *parm = opaque;
|
|
||||||
const char *keyword = line;
|
|
||||||
int keywordlen;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
|
|
||||||
;
|
|
||||||
while (spacep (line))
|
|
||||||
line++;
|
|
||||||
|
|
||||||
if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
|
|
||||||
{
|
|
||||||
xfree (parm->serialno);
|
|
||||||
parm->serialno = store_serialno (line);
|
|
||||||
}
|
|
||||||
else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
|
|
||||||
{
|
|
||||||
xfree (parm->disp_name);
|
|
||||||
parm->disp_name = unescape_status_string (line);
|
|
||||||
}
|
|
||||||
else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
|
|
||||||
{
|
|
||||||
xfree (parm->disp_lang);
|
|
||||||
parm->disp_lang = unescape_status_string (line);
|
|
||||||
}
|
|
||||||
else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
|
|
||||||
{
|
|
||||||
parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
|
|
||||||
}
|
|
||||||
else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
|
|
||||||
{
|
|
||||||
xfree (parm->pubkey_url);
|
|
||||||
parm->pubkey_url = unescape_status_string (line);
|
|
||||||
}
|
|
||||||
else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
|
|
||||||
{
|
|
||||||
xfree (parm->login_data);
|
|
||||||
parm->login_data = unescape_status_string (line);
|
|
||||||
}
|
|
||||||
else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
|
|
||||||
{
|
|
||||||
parm->sig_counter = strtoul (line, NULL, 0);
|
|
||||||
}
|
|
||||||
else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
|
|
||||||
{
|
|
||||||
char *p, *buf;
|
|
||||||
|
|
||||||
buf = p = unescape_status_string (line);
|
|
||||||
if (buf)
|
|
||||||
{
|
|
||||||
while (spacep (p))
|
|
||||||
p++;
|
|
||||||
parm->chv1_cached = atoi (p);
|
|
||||||
while (*p && !spacep (p))
|
|
||||||
p++;
|
|
||||||
while (spacep (p))
|
|
||||||
p++;
|
|
||||||
for (i=0; *p && i < 3; i++)
|
|
||||||
{
|
|
||||||
parm->chvmaxlen[i] = atoi (p);
|
|
||||||
while (*p && !spacep (p))
|
|
||||||
p++;
|
|
||||||
while (spacep (p))
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
for (i=0; *p && i < 3; i++)
|
|
||||||
{
|
|
||||||
parm->chvretry[i] = atoi (p);
|
|
||||||
while (*p && !spacep (p))
|
|
||||||
p++;
|
|
||||||
while (spacep (p))
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
xfree (buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
|
|
||||||
{
|
|
||||||
int no = atoi (line);
|
|
||||||
while (*line && !spacep (line))
|
|
||||||
line++;
|
|
||||||
while (spacep (line))
|
|
||||||
line++;
|
|
||||||
if (no == 1)
|
|
||||||
parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
|
|
||||||
else if (no == 2)
|
|
||||||
parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
|
|
||||||
else if (no == 3)
|
|
||||||
parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call the agent to learn about a smartcard */
|
|
||||||
int
|
|
||||||
agent_learn (struct agent_card_info_s *info)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = start_agent ();
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
memset (info, 0, sizeof *info);
|
|
||||||
rc = assuan_transact (agent_ctx, "LEARN --send",
|
|
||||||
NULL, NULL, NULL, NULL,
|
|
||||||
learn_status_cb, info);
|
|
||||||
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call the agent to retrieve a data object. This function returns
|
|
||||||
the data in the same structure as used by the learn command. It is
|
|
||||||
allowed to update such a structure using this commmand. */
|
|
||||||
int
|
|
||||||
agent_scd_getattr (const char *name, struct agent_card_info_s *info)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
char line[ASSUAN_LINELENGTH];
|
|
||||||
|
|
||||||
if (!*name)
|
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
|
||||||
|
|
||||||
/* We assume that NAME does not need escaping. */
|
|
||||||
if (12 + strlen (name) > DIM(line)-1)
|
|
||||||
return gpg_error (GPG_ERR_TOO_LARGE);
|
|
||||||
stpcpy (stpcpy (line, "SCD GETATTR "), name);
|
|
||||||
|
|
||||||
rc = start_agent ();
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
|
|
||||||
learn_status_cb, info);
|
|
||||||
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Send an setattr command to the SCdaemon. */
|
|
||||||
int
|
|
||||||
agent_scd_setattr (const char *name,
|
|
||||||
const unsigned char *value, size_t valuelen)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
char line[ASSUAN_LINELENGTH];
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
if (!*name || !valuelen)
|
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
|
||||||
|
|
||||||
/* We assume that NAME does not need escaping. */
|
|
||||||
if (12 + strlen (name) > DIM(line)-1)
|
|
||||||
return gpg_error (GPG_ERR_TOO_LARGE);
|
|
||||||
|
|
||||||
p = stpcpy (stpcpy (line, "SCD SETATTR "), name);
|
|
||||||
*p++ = ' ';
|
|
||||||
for (; valuelen; value++, valuelen--)
|
|
||||||
{
|
|
||||||
if (p >= line + DIM(line)-5 )
|
|
||||||
return gpg_error (GPG_ERR_TOO_LARGE);
|
|
||||||
if (*value < ' ' || *value == '+' || *value == '%')
|
|
||||||
{
|
|
||||||
sprintf (p, "%%%02X", *value);
|
|
||||||
p += 3;
|
|
||||||
}
|
|
||||||
else if (*value == ' ')
|
|
||||||
*p++ = '+';
|
|
||||||
else
|
|
||||||
*p++ = *value;
|
|
||||||
}
|
|
||||||
*p = 0;
|
|
||||||
|
|
||||||
rc = start_agent ();
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Status callback for the SCD GENKEY command. */
|
|
||||||
static AssuanError
|
|
||||||
scd_genkey_cb (void *opaque, const char *line)
|
|
||||||
{
|
|
||||||
struct agent_card_genkey_s *parm = opaque;
|
|
||||||
const char *keyword = line;
|
|
||||||
int keywordlen;
|
|
||||||
gpg_error_t rc;
|
|
||||||
|
|
||||||
log_debug ("got status line `%s'\n", line);
|
|
||||||
for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
|
|
||||||
;
|
|
||||||
while (spacep (line))
|
|
||||||
line++;
|
|
||||||
|
|
||||||
if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
|
|
||||||
{
|
|
||||||
parm->fprvalid = unhexify_fpr (line, parm->fpr);
|
|
||||||
}
|
|
||||||
if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
|
|
||||||
{
|
|
||||||
gcry_mpi_t a;
|
|
||||||
const char *name = line;
|
|
||||||
|
|
||||||
while (*line && !spacep (line))
|
|
||||||
line++;
|
|
||||||
while (spacep (line))
|
|
||||||
line++;
|
|
||||||
|
|
||||||
rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL);
|
|
||||||
if (rc)
|
|
||||||
log_error ("error parsing received key data: %s\n", gpg_strerror (rc));
|
|
||||||
else if (*name == 'n' && spacep (name+1))
|
|
||||||
parm->n = a;
|
|
||||||
else if (*name == 'e' && spacep (name+1))
|
|
||||||
parm->e = a;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log_info ("unknown parameter name in received key data\n");
|
|
||||||
gcry_mpi_release (a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
|
|
||||||
{
|
|
||||||
parm->created_at = (u32)strtoul (line, NULL, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send a GENKEY command to the SCdaemon. */
|
|
||||||
int
|
|
||||||
agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
char line[ASSUAN_LINELENGTH];
|
|
||||||
|
|
||||||
rc = start_agent ();
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
memset (info, 0, sizeof *info);
|
|
||||||
snprintf (line, DIM(line)-1, "SCD GENKEY %s%d",
|
|
||||||
force? "--force ":"", keyno);
|
|
||||||
line[DIM(line)-1] = 0;
|
|
||||||
|
|
||||||
memset (info, 0, sizeof *info);
|
|
||||||
rc = assuan_transact (agent_ctx, line,
|
|
||||||
NULL, NULL, NULL, NULL,
|
|
||||||
scd_genkey_cb, info);
|
|
||||||
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static AssuanError
|
|
||||||
membuf_data_cb (void *opaque, const void *buffer, size_t length)
|
|
||||||
{
|
|
||||||
membuf_t *data = opaque;
|
|
||||||
|
|
||||||
if (buffer)
|
|
||||||
put_membuf (data, buffer, length);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send a sign command to the scdaemon via gpg-agent's pass thru
|
|
||||||
mechanism. */
|
|
||||||
int
|
|
||||||
agent_scd_pksign (const char *serialno, int hashalgo,
|
|
||||||
const unsigned char *indata, size_t indatalen,
|
|
||||||
char **r_buf, size_t *r_buflen)
|
|
||||||
{
|
|
||||||
int rc, i;
|
|
||||||
char *p, line[ASSUAN_LINELENGTH];
|
|
||||||
membuf_t data;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
/* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */
|
|
||||||
|
|
||||||
*r_buf = NULL;
|
|
||||||
*r_buflen = 0;
|
|
||||||
|
|
||||||
rc = start_agent ();
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
if (indatalen*2 + 50 > DIM(line))
|
|
||||||
return gpg_error (GPG_ERR_GENERAL);
|
|
||||||
|
|
||||||
sprintf (line, "SCD SETDATA ");
|
|
||||||
p = line + strlen (line);
|
|
||||||
for (i=0; i < indatalen ; i++, p += 2 )
|
|
||||||
sprintf (p, "%02X", indata[i]);
|
|
||||||
rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
||||||
if (rc)
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
|
|
||||||
init_membuf (&data, 1024);
|
|
||||||
#if 0
|
|
||||||
if (!hashalgo) /* Temporary test hack. */
|
|
||||||
snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
snprintf (line, DIM(line)-1, "SCD PKSIGN %s", serialno);
|
|
||||||
line[DIM(line)-1] = 0;
|
|
||||||
rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
|
|
||||||
NULL, NULL, NULL, NULL);
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
xfree (get_membuf (&data, &len));
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
*r_buf = get_membuf (&data, r_buflen);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Decrypt INDATA of length INDATALEN using the card identified by
|
|
||||||
SERIALNO. Return the plaintext in a nwly allocated buffer stored
|
|
||||||
at the address of R_BUF.
|
|
||||||
|
|
||||||
Note, we currently support only RSA or more exactly algorithms
|
|
||||||
taking one input data element. */
|
|
||||||
int
|
|
||||||
agent_scd_pkdecrypt (const char *serialno,
|
|
||||||
const unsigned char *indata, size_t indatalen,
|
|
||||||
char **r_buf, size_t *r_buflen)
|
|
||||||
{
|
|
||||||
int rc, i;
|
|
||||||
char *p, line[ASSUAN_LINELENGTH];
|
|
||||||
membuf_t data;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
*r_buf = NULL;
|
|
||||||
rc = start_agent ();
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
/* FIXME: use secure memory where appropriate */
|
|
||||||
if (indatalen*2 + 50 > DIM(line))
|
|
||||||
return gpg_error (GPG_ERR_GENERAL);
|
|
||||||
|
|
||||||
sprintf (line, "SCD SETDATA ");
|
|
||||||
p = line + strlen (line);
|
|
||||||
for (i=0; i < indatalen ; i++, p += 2 )
|
|
||||||
sprintf (p, "%02X", indata[i]);
|
|
||||||
rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
||||||
if (rc)
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
|
|
||||||
init_membuf (&data, 1024);
|
|
||||||
snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
|
|
||||||
line[DIM(line)-1] = 0;
|
|
||||||
rc = assuan_transact (agent_ctx, line,
|
|
||||||
membuf_data_cb, &data,
|
|
||||||
NULL, NULL, NULL, NULL);
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
xfree (get_membuf (&data, &len));
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
*r_buf = get_membuf (&data, r_buflen);
|
|
||||||
if (!*r_buf)
|
|
||||||
return gpg_error (GPG_ERR_ENOMEM);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Change the PIN of an OpenPGP card or reset the retry counter.
|
|
||||||
CHVNO 1: Change the PIN
|
|
||||||
2: Same as 1
|
|
||||||
3: Change the admin PIN
|
|
||||||
101: Set a new PIN and reset the retry counter
|
|
||||||
102: Same as 101
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
agent_scd_change_pin (int chvno)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
char line[ASSUAN_LINELENGTH];
|
|
||||||
const char *reset = "";
|
|
||||||
|
|
||||||
if (chvno >= 100)
|
|
||||||
reset = "--reset";
|
|
||||||
chvno %= 100;
|
|
||||||
|
|
||||||
rc = start_agent ();
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno);
|
|
||||||
line[DIM(line)-1] = 0;
|
|
||||||
rc = assuan_transact (agent_ctx, line, NULL, NULL,
|
|
||||||
NULL, NULL, NULL, NULL);
|
|
||||||
return map_assuan_err (rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Perform a CHECKPIN operation. SERIALNO should be the serial
|
|
||||||
number of the card - optioanlly followed by the fingerprint;
|
|
||||||
however the fingerprint is ignored here. */
|
|
||||||
int
|
|
||||||
agent_scd_checkpin (const char *serialno)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
char line[ASSUAN_LINELENGTH];
|
|
||||||
|
|
||||||
rc = start_agent ();
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno);
|
|
||||||
line[DIM(line)-1] = 0;
|
|
||||||
return assuan_transact (agent_ctx, line,
|
|
||||||
NULL, NULL,
|
|
||||||
NULL, NULL, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,94 +0,0 @@
|
|||||||
/* call-agent.h - Divert operations to the agent
|
|
||||||
* Copyright (C) 2003 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 GNUPG_G10_CALL_AGENT_H
|
|
||||||
#define GNUPG_G10_CALL_AGENT_H
|
|
||||||
|
|
||||||
|
|
||||||
struct agent_card_info_s {
|
|
||||||
int error; /* private. */
|
|
||||||
char *serialno; /* malloced hex string. */
|
|
||||||
char *disp_name; /* malloced. */
|
|
||||||
char *disp_lang; /* malloced. */
|
|
||||||
int disp_sex; /* 0 = unspecified, 1 = male, 2 = female */
|
|
||||||
char *pubkey_url; /* malloced. */
|
|
||||||
char *login_data; /* malloced. */
|
|
||||||
char fpr1valid;
|
|
||||||
char fpr2valid;
|
|
||||||
char fpr3valid;
|
|
||||||
char fpr1[20];
|
|
||||||
char fpr2[20];
|
|
||||||
char fpr3[20];
|
|
||||||
unsigned long sig_counter;
|
|
||||||
int chv1_cached; /* True if a PIN is not required for each
|
|
||||||
signing. Note that the gpg-agent might cache
|
|
||||||
it anyway. */
|
|
||||||
int chvmaxlen[3]; /* Maximum allowed length of a CHV. */
|
|
||||||
int chvretry[3]; /* Allowed retries for the CHV; 0 = blocked. */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct agent_card_genkey_s {
|
|
||||||
char fprvalid;
|
|
||||||
char fpr[20];
|
|
||||||
u32 created_at;
|
|
||||||
gcry_mpi_t n;
|
|
||||||
gcry_mpi_t e;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Release the card info structure. */
|
|
||||||
void agent_release_card_info (struct agent_card_info_s *info);
|
|
||||||
|
|
||||||
/* Return card info. */
|
|
||||||
int agent_learn (struct agent_card_info_s *info);
|
|
||||||
|
|
||||||
/* Update INFO with the attribute NAME. */
|
|
||||||
int agent_scd_getattr (const char *name, struct agent_card_info_s *info);
|
|
||||||
|
|
||||||
/* Check whether the secret key for the key identified by HEXKEYGRIP
|
|
||||||
is available. Return 0 for yes or an error code. */
|
|
||||||
int agent_havekey (const char *hexkeygrip);
|
|
||||||
|
|
||||||
/* Send a SETATTR command to the SCdaemon. */
|
|
||||||
int agent_scd_setattr (const char *name,
|
|
||||||
const unsigned char *value, size_t valuelen);
|
|
||||||
|
|
||||||
/* Send a GENKEY command to the SCdaemon. */
|
|
||||||
int agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force);
|
|
||||||
|
|
||||||
/* Send a PKSIGN command to the SCdaemon. */
|
|
||||||
int agent_scd_pksign (const char *keyid, int hashalgo,
|
|
||||||
const unsigned char *indata, size_t indatalen,
|
|
||||||
char **r_buf, size_t *r_buflen);
|
|
||||||
|
|
||||||
/* Send a PKDECRYPT command to the SCdaemon. */
|
|
||||||
int agent_scd_pkdecrypt (const char *serialno,
|
|
||||||
const unsigned char *indata, size_t indatalen,
|
|
||||||
char **r_buf, size_t *r_buflen);
|
|
||||||
|
|
||||||
/* Change the PIN of an OpenPGP card or reset the retry counter. */
|
|
||||||
int agent_scd_change_pin (int chvno);
|
|
||||||
|
|
||||||
/* Send the CHECKPIN command to the SCdaemon. */
|
|
||||||
int agent_scd_checkpin (const char *serialno);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*GNUPG_G10_CALL_AGENT_H*/
|
|
||||||
|
|
884
g10/card-util.c
884
g10/card-util.c
@ -1,884 +0,0 @@
|
|||||||
/* card-util.c - Utility functions for the OpenPGP card.
|
|
||||||
* Copyright (C) 2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#if GNUPG_MAJOR_VERSION != 1
|
|
||||||
#include "gpg.h"
|
|
||||||
#endif
|
|
||||||
#include "util.h"
|
|
||||||
#include "i18n.h"
|
|
||||||
#include "ttyio.h"
|
|
||||||
#include "status.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "main.h"
|
|
||||||
#if GNUPG_MAJOR_VERSION == 1
|
|
||||||
#include "cardglue.h"
|
|
||||||
#else
|
|
||||||
#include "call-agent.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define CONTROL_D ('D' - 'A' + 1)
|
|
||||||
|
|
||||||
|
|
||||||
/* Change the PIN of a an OpenPGP card. This is an interactive
|
|
||||||
function. */
|
|
||||||
void
|
|
||||||
change_pin (int chvno)
|
|
||||||
{
|
|
||||||
struct agent_card_info_s info;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = agent_learn (&info);
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
log_error (_("OpenPGP card not available: %s\n"),
|
|
||||||
gpg_strerror (rc));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_info (_("OpenPGP card no. %s detected\n"),
|
|
||||||
info.serialno? info.serialno : "[none]");
|
|
||||||
|
|
||||||
agent_release_card_info (&info);
|
|
||||||
|
|
||||||
if (opt.batch)
|
|
||||||
{
|
|
||||||
log_error (_("sorry, can't do this in batch mode\n"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
char *answer;
|
|
||||||
|
|
||||||
tty_printf ("\n");
|
|
||||||
tty_printf ("1 - change PIN\n"
|
|
||||||
"2 - unblock PIN\n"
|
|
||||||
"3 - change Admin PIN\n"
|
|
||||||
"Q - quit\n");
|
|
||||||
tty_printf ("\n");
|
|
||||||
|
|
||||||
answer = cpr_get("cardutil.change_pin.menu",_("Your selection? "));
|
|
||||||
cpr_kill_prompt();
|
|
||||||
if (strlen (answer) != 1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
rc = 0;
|
|
||||||
if (*answer == '1')
|
|
||||||
{
|
|
||||||
rc = agent_scd_change_pin (1);
|
|
||||||
if (rc)
|
|
||||||
tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
|
|
||||||
else
|
|
||||||
tty_printf ("PIN changed.\n");
|
|
||||||
}
|
|
||||||
else if (*answer == '2')
|
|
||||||
{
|
|
||||||
rc = agent_scd_change_pin (101);
|
|
||||||
if (rc)
|
|
||||||
tty_printf ("Error unblocking the PIN: %s\n", gpg_strerror (rc));
|
|
||||||
else
|
|
||||||
tty_printf ("PIN unblocked and new PIN set.\n");
|
|
||||||
}
|
|
||||||
else if (*answer == '3')
|
|
||||||
{
|
|
||||||
rc = agent_scd_change_pin (3);
|
|
||||||
if (rc)
|
|
||||||
tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
|
|
||||||
else
|
|
||||||
tty_printf ("PIN changed.\n");
|
|
||||||
}
|
|
||||||
else if (*answer == 'q' || *answer == 'Q')
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
get_manufacturer (unsigned int no)
|
|
||||||
{
|
|
||||||
/* Note: Make sure that there is no colon or linefeed in the string. */
|
|
||||||
switch (no)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
case 0xffff: return "test card";
|
|
||||||
case 0x0001: return "PPC Card Systems";
|
|
||||||
default: return "unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_sha1_fpr (FILE *fp, const unsigned char *fpr)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (fpr)
|
|
||||||
{
|
|
||||||
for (i=0; i < 20 ; i+=2, fpr += 2 )
|
|
||||||
{
|
|
||||||
if (i == 10 )
|
|
||||||
tty_fprintf (fp, " ");
|
|
||||||
tty_fprintf (fp, " %02X%02X", *fpr, fpr[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
tty_fprintf (fp, " [none]");
|
|
||||||
tty_fprintf (fp, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_sha1_fpr_colon (FILE *fp, const unsigned char *fpr)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (fpr)
|
|
||||||
{
|
|
||||||
for (i=0; i < 20 ; i++, fpr++)
|
|
||||||
fprintf (fp, "%02X", *fpr);
|
|
||||||
}
|
|
||||||
putc (':', fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_name (FILE *fp, const char *text, const char *name)
|
|
||||||
{
|
|
||||||
tty_fprintf (fp, "%s", text);
|
|
||||||
|
|
||||||
/* FIXME: tty_printf_utf8_string2 eats everything after and
|
|
||||||
including an @ - e.g. when printing an url. */
|
|
||||||
if (name && *name)
|
|
||||||
{
|
|
||||||
if (fp)
|
|
||||||
print_utf8_string2 (fp, name, strlen (name), '\n');
|
|
||||||
else
|
|
||||||
tty_print_utf8_string2 (name, strlen (name), 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
tty_fprintf (fp, _("[not set]"));
|
|
||||||
tty_fprintf (fp, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_isoname (FILE *fp, const char *text, const char *tag, const char *name)
|
|
||||||
{
|
|
||||||
if (opt.with_colons)
|
|
||||||
fprintf (fp, "%s:", tag);
|
|
||||||
else
|
|
||||||
tty_fprintf (fp, "%s", text);
|
|
||||||
|
|
||||||
if (name && *name)
|
|
||||||
{
|
|
||||||
char *p, *given, *buf = xstrdup (name);
|
|
||||||
|
|
||||||
given = strstr (buf, "<<");
|
|
||||||
for (p=buf; *p; p++)
|
|
||||||
if (*p == '<')
|
|
||||||
*p = ' ';
|
|
||||||
if (given && given[2])
|
|
||||||
{
|
|
||||||
*given = 0;
|
|
||||||
given += 2;
|
|
||||||
if (opt.with_colons)
|
|
||||||
print_string (fp, given, strlen (given), ':');
|
|
||||||
else if (fp)
|
|
||||||
print_utf8_string2 (fp, given, strlen (given), '\n');
|
|
||||||
else
|
|
||||||
tty_print_utf8_string2 (given, strlen (given), 0);
|
|
||||||
|
|
||||||
if (opt.with_colons)
|
|
||||||
putc (':', fp);
|
|
||||||
else if (*buf)
|
|
||||||
tty_fprintf (fp, " ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt.with_colons)
|
|
||||||
print_string (fp, buf, strlen (buf), ':');
|
|
||||||
else if (fp)
|
|
||||||
print_utf8_string2 (fp, buf, strlen (buf), '\n');
|
|
||||||
else
|
|
||||||
tty_print_utf8_string2 (buf, strlen (buf), 0);
|
|
||||||
xfree (buf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (opt.with_colons)
|
|
||||||
putc (':', fp);
|
|
||||||
else
|
|
||||||
tty_fprintf (fp, _("[not set]"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt.with_colons)
|
|
||||||
fputs (":\n", fp);
|
|
||||||
else
|
|
||||||
tty_fprintf (fp, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return true if the SHA1 fingerprint FPR consists only of zeroes. */
|
|
||||||
static int
|
|
||||||
fpr_is_zero (const char *fpr)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0; i < 20 && !fpr[i]; i++)
|
|
||||||
;
|
|
||||||
return (i == 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Print all available information about the current card. */
|
|
||||||
void
|
|
||||||
card_status (FILE *fp, char *serialno, size_t serialnobuflen)
|
|
||||||
{
|
|
||||||
struct agent_card_info_s info;
|
|
||||||
PKT_public_key *pk = xcalloc (1, sizeof *pk);
|
|
||||||
int rc;
|
|
||||||
unsigned int uval;
|
|
||||||
|
|
||||||
if (serialno && serialnobuflen)
|
|
||||||
*serialno = 0;
|
|
||||||
|
|
||||||
rc = agent_learn (&info);
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
if (opt.with_colons)
|
|
||||||
fputs ("AID:::\n", fp);
|
|
||||||
log_error (_("OpenPGP card not available: %s\n"),
|
|
||||||
gpg_strerror (rc));
|
|
||||||
xfree (pk);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt.with_colons)
|
|
||||||
fprintf (fp, "AID:%s:", info.serialno? info.serialno : "");
|
|
||||||
else
|
|
||||||
tty_fprintf (fp, "Application ID ...: %s\n",
|
|
||||||
info.serialno? info.serialno : "[none]");
|
|
||||||
if (!info.serialno || strncmp (info.serialno, "D27600012401", 12)
|
|
||||||
|| strlen (info.serialno) != 32 )
|
|
||||||
{
|
|
||||||
if (opt.with_colons)
|
|
||||||
fputs ("unknown:\n", fp);
|
|
||||||
log_info ("not an OpenPGP card\n");
|
|
||||||
agent_release_card_info (&info);
|
|
||||||
xfree (pk);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!serialno)
|
|
||||||
;
|
|
||||||
else if (strlen (serialno)+1 > serialnobuflen)
|
|
||||||
log_error ("serial number longer than expected\n");
|
|
||||||
else
|
|
||||||
strcpy (serialno, info.serialno);
|
|
||||||
|
|
||||||
if (opt.with_colons)
|
|
||||||
fputs ("openpgp-card:\n", fp);
|
|
||||||
|
|
||||||
|
|
||||||
if (opt.with_colons)
|
|
||||||
{
|
|
||||||
fprintf (fp, "version:%.4s:\n", info.serialno+12);
|
|
||||||
uval = xtoi_2(info.serialno+16)*256 + xtoi_2 (info.serialno+18);
|
|
||||||
fprintf (fp, "vendor:%04x:%s:\n", uval, get_manufacturer (uval));
|
|
||||||
fprintf (fp, "serial:%.8s:\n", info.serialno+20);
|
|
||||||
|
|
||||||
print_isoname (fp, "Name of cardholder: ", "name", info.disp_name);
|
|
||||||
|
|
||||||
fputs ("lang:", fp);
|
|
||||||
if (info.disp_lang)
|
|
||||||
print_string (fp, info.disp_lang, strlen (info.disp_lang), ':');
|
|
||||||
fputs (":\n", fp);
|
|
||||||
|
|
||||||
fprintf (fp, "sex:%c:\n", (info.disp_sex == 1? 'm':
|
|
||||||
info.disp_sex == 2? 'f' : 'u'));
|
|
||||||
|
|
||||||
fputs ("url:", fp);
|
|
||||||
if (info.pubkey_url)
|
|
||||||
print_string (fp, info.pubkey_url, strlen (info.pubkey_url), ':');
|
|
||||||
fputs (":\n", fp);
|
|
||||||
|
|
||||||
fputs ("login:", fp);
|
|
||||||
if (info.login_data)
|
|
||||||
print_string (fp, info.login_data, strlen (info.login_data), ':');
|
|
||||||
fputs (":\n", fp);
|
|
||||||
|
|
||||||
fprintf (fp, "forcepin:%d:::\n", !info.chv1_cached);
|
|
||||||
fprintf (fp, "maxpinlen:%d:%d:%d:\n",
|
|
||||||
info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]);
|
|
||||||
fprintf (fp, "pinretry:%d:%d:%d:\n",
|
|
||||||
info.chvretry[0], info.chvretry[1], info.chvretry[2]);
|
|
||||||
fprintf (fp, "sigcount:%lu:::\n", info.sig_counter);
|
|
||||||
|
|
||||||
fputs ("fpr:", fp);
|
|
||||||
print_sha1_fpr_colon (fp, info.fpr1valid? info.fpr1:NULL);
|
|
||||||
print_sha1_fpr_colon (fp, info.fpr2valid? info.fpr2:NULL);
|
|
||||||
print_sha1_fpr_colon (fp, info.fpr3valid? info.fpr3:NULL);
|
|
||||||
putc ('\n', fp);
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tty_fprintf (fp, "Version ..........: %.1s%c.%.1s%c\n",
|
|
||||||
info.serialno[12] == '0'?"":info.serialno+12,
|
|
||||||
info.serialno[13],
|
|
||||||
info.serialno[14] == '0'?"":info.serialno+14,
|
|
||||||
info.serialno[15]);
|
|
||||||
tty_fprintf (fp, "Manufacturer .....: %s\n",
|
|
||||||
get_manufacturer (xtoi_2(info.serialno+16)*256
|
|
||||||
+ xtoi_2 (info.serialno+18)));
|
|
||||||
tty_fprintf (fp, "Serial number ....: %.8s\n", info.serialno+20);
|
|
||||||
|
|
||||||
print_isoname (fp, "Name of cardholder: ", "name", info.disp_name);
|
|
||||||
print_name (fp, "Language prefs ...: ", info.disp_lang);
|
|
||||||
tty_fprintf (fp, "Sex ..............: %s\n",
|
|
||||||
info.disp_sex == 1? _("male"):
|
|
||||||
info.disp_sex == 2? _("female") : _("unspecified"));
|
|
||||||
print_name (fp, "URL of public key : ", info.pubkey_url);
|
|
||||||
print_name (fp, "Login data .......: ", info.login_data);
|
|
||||||
tty_fprintf (fp, "Signature PIN ....: %s\n",
|
|
||||||
info.chv1_cached? _("not forced"): _("forced"));
|
|
||||||
tty_fprintf (fp, "Max. PIN lengths .: %d %d %d\n",
|
|
||||||
info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]);
|
|
||||||
tty_fprintf (fp, "PIN retry counter : %d %d %d\n",
|
|
||||||
info.chvretry[0], info.chvretry[1], info.chvretry[2]);
|
|
||||||
tty_fprintf (fp, "Signature counter : %lu\n", info.sig_counter);
|
|
||||||
tty_fprintf (fp, "Signature key ....:");
|
|
||||||
print_sha1_fpr (fp, info.fpr1valid? info.fpr1:NULL);
|
|
||||||
tty_fprintf (fp, "Encryption key....:");
|
|
||||||
print_sha1_fpr (fp, info.fpr2valid? info.fpr2:NULL);
|
|
||||||
tty_fprintf (fp, "Authentication key:");
|
|
||||||
print_sha1_fpr (fp, info.fpr3valid? info.fpr3:NULL);
|
|
||||||
tty_fprintf (fp, "General key info..: ");
|
|
||||||
if (info.fpr1valid && !get_pubkey_byfprint (pk, info.fpr1, 20))
|
|
||||||
print_pubkey_info (fp, pk);
|
|
||||||
else
|
|
||||||
tty_fprintf (fp, "[none]\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
free_public_key (pk);
|
|
||||||
agent_release_card_info (&info);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static char *
|
|
||||||
get_one_name (const char *prompt1, const char *prompt2)
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
name = cpr_get (prompt1, prompt2);
|
|
||||||
if (!name)
|
|
||||||
return NULL;
|
|
||||||
trim_spaces (name);
|
|
||||||
cpr_kill_prompt ();
|
|
||||||
for (i=0; name[i] && name[i] >= ' ' && name[i] <= 126; i++)
|
|
||||||
;
|
|
||||||
|
|
||||||
/* The name must be in Latin-1 and not UTF-8 - lacking the code
|
|
||||||
to ensure this we restrict it to ASCII. */
|
|
||||||
if (name[i])
|
|
||||||
tty_printf (_("Error: Only plain ASCII is currently allowed.\n"));
|
|
||||||
else if (strchr (name, '<'))
|
|
||||||
tty_printf (_("Error: The \"<\" character may not be used.\n"));
|
|
||||||
else if (strstr (name, " "))
|
|
||||||
tty_printf (_("Error: Double spaces are not allowed.\n"));
|
|
||||||
else
|
|
||||||
return name;
|
|
||||||
xfree (name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
change_name (void)
|
|
||||||
{
|
|
||||||
char *surname = NULL, *givenname = NULL;
|
|
||||||
char *isoname, *p;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
surname = get_one_name ("keygen.smartcard.surname",
|
|
||||||
_("Cardholder's surname: "));
|
|
||||||
givenname = get_one_name ("keygen.smartcard.givenname",
|
|
||||||
_("Cardholder's given name: "));
|
|
||||||
if (!surname || !givenname || (!*surname && !*givenname))
|
|
||||||
{
|
|
||||||
xfree (surname);
|
|
||||||
xfree (givenname);
|
|
||||||
return -1; /*canceled*/
|
|
||||||
}
|
|
||||||
|
|
||||||
isoname = xmalloc ( strlen (surname) + 2 + strlen (givenname) + 1);
|
|
||||||
strcpy (stpcpy (stpcpy (isoname, surname), "<<"), givenname);
|
|
||||||
xfree (surname);
|
|
||||||
xfree (givenname);
|
|
||||||
for (p=isoname; *p; p++)
|
|
||||||
if (*p == ' ')
|
|
||||||
*p = '<';
|
|
||||||
|
|
||||||
if (strlen (isoname) > 39 )
|
|
||||||
{
|
|
||||||
tty_printf (_("Error: Combined name too long "
|
|
||||||
"(limit is %d characters).\n"), 39);
|
|
||||||
xfree (isoname);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_debug ("setting Name to `%s'\n", isoname);
|
|
||||||
rc = agent_scd_setattr ("DISP-NAME", isoname, strlen (isoname) );
|
|
||||||
if (rc)
|
|
||||||
log_error ("error setting Name: %s\n", gpg_strerror (rc));
|
|
||||||
|
|
||||||
xfree (isoname);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
change_url (void)
|
|
||||||
{
|
|
||||||
char *url;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
url = cpr_get ("cardedit.change_url", _("URL to retrieve public key: "));
|
|
||||||
if (!url)
|
|
||||||
return -1;
|
|
||||||
trim_spaces (url);
|
|
||||||
cpr_kill_prompt ();
|
|
||||||
|
|
||||||
if (strlen (url) > 254 )
|
|
||||||
{
|
|
||||||
tty_printf (_("Error: URL too long "
|
|
||||||
"(limit is %d characters).\n"), 254);
|
|
||||||
xfree (url);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = agent_scd_setattr ("PUBKEY-URL", url, strlen (url) );
|
|
||||||
if (rc)
|
|
||||||
log_error ("error setting URL: %s\n", gpg_strerror (rc));
|
|
||||||
xfree (url);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
change_login (void)
|
|
||||||
{
|
|
||||||
char *data;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
data = cpr_get ("cardedit.change_login",
|
|
||||||
_("Login data (account name): "));
|
|
||||||
if (!data)
|
|
||||||
return -1;
|
|
||||||
trim_spaces (data);
|
|
||||||
cpr_kill_prompt ();
|
|
||||||
|
|
||||||
if (strlen (data) > 254 )
|
|
||||||
{
|
|
||||||
tty_printf (_("Error: Login data too long "
|
|
||||||
"(limit is %d characters).\n"), 254);
|
|
||||||
xfree (data);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = agent_scd_setattr ("LOGIN-DATA", data, strlen (data) );
|
|
||||||
if (rc)
|
|
||||||
log_error ("error setting login data: %s\n", gpg_strerror (rc));
|
|
||||||
xfree (data);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
change_lang (void)
|
|
||||||
{
|
|
||||||
char *data, *p;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
data = cpr_get ("cardedit.change_lang",
|
|
||||||
_("Language preferences: "));
|
|
||||||
if (!data)
|
|
||||||
return -1;
|
|
||||||
trim_spaces (data);
|
|
||||||
cpr_kill_prompt ();
|
|
||||||
|
|
||||||
if (strlen (data) > 8 || (strlen (data) & 1))
|
|
||||||
{
|
|
||||||
tty_printf (_("Error: invalid length of preference string.\n"));
|
|
||||||
xfree (data);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (p=data; *p && *p >= 'a' && *p <= 'z'; p++)
|
|
||||||
;
|
|
||||||
if (*p)
|
|
||||||
{
|
|
||||||
tty_printf (_("Error: invalid characters in preference string.\n"));
|
|
||||||
xfree (data);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = agent_scd_setattr ("DISP-LANG", data, strlen (data) );
|
|
||||||
if (rc)
|
|
||||||
log_error ("error setting lang: %s\n", gpg_strerror (rc));
|
|
||||||
xfree (data);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
change_sex (void)
|
|
||||||
{
|
|
||||||
char *data;
|
|
||||||
const char *str;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
data = cpr_get ("cardedit.change_sex",
|
|
||||||
_("Sex ((M)ale, (F)emale or space): "));
|
|
||||||
if (!data)
|
|
||||||
return -1;
|
|
||||||
trim_spaces (data);
|
|
||||||
cpr_kill_prompt ();
|
|
||||||
|
|
||||||
if (!*data)
|
|
||||||
str = "9";
|
|
||||||
else if ((*data == 'M' || *data == 'm') && !data[1])
|
|
||||||
str = "1";
|
|
||||||
else if ((*data == 'F' || *data == 'f') && !data[1])
|
|
||||||
str = "2";
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tty_printf (_("Error: invalid response.\n"));
|
|
||||||
xfree (data);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = agent_scd_setattr ("DISP-SEX", str, 1 );
|
|
||||||
if (rc)
|
|
||||||
log_error ("error setting sex: %s\n", gpg_strerror (rc));
|
|
||||||
xfree (data);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
toggle_forcesig (void)
|
|
||||||
{
|
|
||||||
struct agent_card_info_s info;
|
|
||||||
int rc;
|
|
||||||
int newstate;
|
|
||||||
|
|
||||||
memset (&info, 0, sizeof info);
|
|
||||||
rc = agent_scd_getattr ("CHV-STATUS", &info);
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
log_error ("error getting current status: %s\n", gpg_strerror (rc));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
newstate = !info.chv1_cached;
|
|
||||||
agent_release_card_info (&info);
|
|
||||||
|
|
||||||
rc = agent_scd_setattr ("CHV-STATUS-1", newstate? "\x01":"", 1);
|
|
||||||
if (rc)
|
|
||||||
log_error ("error toggling signature PIN flag: %s\n", gpg_strerror (rc));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
generate_card_keys (const char *serialno)
|
|
||||||
{
|
|
||||||
struct agent_card_info_s info;
|
|
||||||
int rc;
|
|
||||||
int forced_chv1;
|
|
||||||
|
|
||||||
memset (&info, 0, sizeof info);
|
|
||||||
rc = agent_scd_getattr ("KEY-FPR", &info);
|
|
||||||
if (!rc)
|
|
||||||
rc = agent_scd_getattr ("SERIALNO", &info);
|
|
||||||
if (!rc)
|
|
||||||
rc = agent_scd_getattr ("CHV-STATUS", &info);
|
|
||||||
if (!rc)
|
|
||||||
rc = agent_scd_getattr ("DISP-NAME", &info);
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
log_error ("error getting current key info: %s\n", gpg_strerror (rc));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ( (info.fpr1valid && !fpr_is_zero (info.fpr1))
|
|
||||||
|| (info.fpr2valid && !fpr_is_zero (info.fpr2))
|
|
||||||
|| (info.fpr3valid && !fpr_is_zero (info.fpr3)))
|
|
||||||
{
|
|
||||||
tty_printf ("\n");
|
|
||||||
log_info ("NOTE: keys are already stored on the card!\n");
|
|
||||||
tty_printf ("\n");
|
|
||||||
if ( !cpr_get_answer_is_yes( "cardedit.genkeys.replace_keys",
|
|
||||||
_("Replace existing keys? ")))
|
|
||||||
{
|
|
||||||
agent_release_card_info (&info);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!info.disp_name || !*info.disp_name)
|
|
||||||
{
|
|
||||||
tty_printf ("\n");
|
|
||||||
tty_printf (_("Please note that the factory settings of the PINs are\n"
|
|
||||||
" PIN = \"%s\" Admin PIN = \"%s\"\n"
|
|
||||||
"You should change them using the command --change-pin\n"),
|
|
||||||
"123456", "12345678");
|
|
||||||
tty_printf ("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
forced_chv1 = !info.chv1_cached;
|
|
||||||
if (forced_chv1)
|
|
||||||
{ /* Switch of the forced mode so that during key generation we
|
|
||||||
don't get bothered with PIN queries for each
|
|
||||||
self-signature. */
|
|
||||||
rc = agent_scd_setattr ("CHV-STATUS-1", "\x01", 1);
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
log_error ("error clearing forced signature PIN flag: %s\n",
|
|
||||||
gpg_strerror (rc));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check the PIN now, so that we won't get asked later for each
|
|
||||||
binding signature. */
|
|
||||||
rc = agent_scd_checkpin (serialno);
|
|
||||||
if (rc)
|
|
||||||
log_error ("error checking the PIN: %s\n", gpg_strerror (rc));
|
|
||||||
else
|
|
||||||
generate_keypair (NULL, info.serialno);
|
|
||||||
|
|
||||||
agent_release_card_info (&info);
|
|
||||||
if (forced_chv1)
|
|
||||||
{ /* Switch back to forced state. */
|
|
||||||
rc = agent_scd_setattr ("CHV-STATUS-1", "", 1);
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
log_error ("error setting forced signature PIN flag: %s\n",
|
|
||||||
gpg_strerror (rc));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Menu to edit all user changeable values on an OpenPGP card. Only
|
|
||||||
Key creation is not handled here. */
|
|
||||||
void
|
|
||||||
card_edit (STRLIST commands)
|
|
||||||
{
|
|
||||||
enum cmdids {
|
|
||||||
cmdNOP = 0,
|
|
||||||
cmdQUIT, cmdHELP, cmdLIST, cmdDEBUG,
|
|
||||||
cmdNAME, cmdURL, cmdLOGIN, cmdLANG, cmdSEX,
|
|
||||||
cmdFORCESIG, cmdGENERATE, cmdPASSWD,
|
|
||||||
cmdINVCMD
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct {
|
|
||||||
const char *name;
|
|
||||||
enum cmdids id;
|
|
||||||
const char *desc;
|
|
||||||
} cmds[] = {
|
|
||||||
{ N_("quit") , cmdQUIT , N_("quit this menu") },
|
|
||||||
{ N_("q") , cmdQUIT , NULL },
|
|
||||||
{ N_("help") , cmdHELP , N_("show this help") },
|
|
||||||
{ "?" , cmdHELP , NULL },
|
|
||||||
{ N_("list") , cmdLIST , N_("list all available data") },
|
|
||||||
{ N_("l") , cmdLIST , NULL },
|
|
||||||
{ N_("debug") , cmdDEBUG , NULL },
|
|
||||||
{ N_("name") , cmdNAME , N_("change card holder's name") },
|
|
||||||
{ N_("url") , cmdURL , N_("change URL to retrieve key") },
|
|
||||||
{ N_("login") , cmdLOGIN , N_("change the login name") },
|
|
||||||
{ N_("lang") , cmdLANG , N_("change the language preferences") },
|
|
||||||
{ N_("sex") , cmdSEX , N_("change card holder's sex") },
|
|
||||||
{ N_("forcesig"),
|
|
||||||
cmdFORCESIG, N_("toggle the signature force PIN flag") },
|
|
||||||
{ N_("generate"),
|
|
||||||
cmdGENERATE, N_("generate new keys") },
|
|
||||||
{ N_("passwd"), cmdPASSWD, N_("menu to change or unblock the PIN") },
|
|
||||||
{ NULL, cmdINVCMD }
|
|
||||||
};
|
|
||||||
|
|
||||||
enum cmdids cmd = cmdNOP;
|
|
||||||
int have_commands = !!commands;
|
|
||||||
int redisplay = 1;
|
|
||||||
char *answer = NULL;
|
|
||||||
int did_checkpin = 0;
|
|
||||||
char serialnobuf[50];
|
|
||||||
|
|
||||||
|
|
||||||
if (opt.command_fd != -1)
|
|
||||||
;
|
|
||||||
else if (opt.batch && !have_commands)
|
|
||||||
{
|
|
||||||
log_error(_("can't do that in batchmode\n"));
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
int arg_number;
|
|
||||||
const char *arg_string = "";
|
|
||||||
char *p;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
tty_printf("\n");
|
|
||||||
if (redisplay )
|
|
||||||
{
|
|
||||||
if (opt.with_colons)
|
|
||||||
{
|
|
||||||
card_status (stdout, serialnobuf, DIM (serialnobuf));
|
|
||||||
fflush (stdout);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
card_status (NULL, serialnobuf, DIM (serialnobuf));
|
|
||||||
tty_printf("\n");
|
|
||||||
}
|
|
||||||
redisplay = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
xfree (answer);
|
|
||||||
if (have_commands)
|
|
||||||
{
|
|
||||||
if (commands)
|
|
||||||
{
|
|
||||||
answer = xstrdup (commands->d);
|
|
||||||
commands = commands->next;
|
|
||||||
}
|
|
||||||
else if (opt.batch)
|
|
||||||
{
|
|
||||||
answer = xstrdup ("quit");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
have_commands = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!have_commands)
|
|
||||||
{
|
|
||||||
answer = cpr_get_no_help("cardedit.prompt", _("Command> "));
|
|
||||||
cpr_kill_prompt();
|
|
||||||
}
|
|
||||||
trim_spaces(answer);
|
|
||||||
}
|
|
||||||
while( *answer == '#' );
|
|
||||||
|
|
||||||
arg_number = 0; /* Yes, here is the init which egcc complains about */
|
|
||||||
if (!*answer)
|
|
||||||
cmd = cmdLIST; /* Default to the list command */
|
|
||||||
else if (*answer == CONTROL_D)
|
|
||||||
cmd = cmdQUIT;
|
|
||||||
else {
|
|
||||||
if ((p=strchr (answer,' ')))
|
|
||||||
{
|
|
||||||
*p++ = 0;
|
|
||||||
trim_spaces (answer);
|
|
||||||
trim_spaces (p);
|
|
||||||
arg_number = atoi(p);
|
|
||||||
arg_string = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; cmds[i].name; i++ )
|
|
||||||
if (!ascii_strcasecmp (answer, cmds[i].name ))
|
|
||||||
break;
|
|
||||||
|
|
||||||
cmd = cmds[i].id;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
switch (cmd)
|
|
||||||
{
|
|
||||||
case cmdHELP:
|
|
||||||
for (i=0; cmds[i].name; i++ )
|
|
||||||
if (cmds[i].desc)
|
|
||||||
tty_printf("%-10s %s\n", cmds[i].name, _(cmds[i].desc) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case cmdLIST:
|
|
||||||
redisplay = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case cmdNAME:
|
|
||||||
change_name ();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case cmdURL:
|
|
||||||
change_url ();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case cmdLOGIN:
|
|
||||||
change_login ();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case cmdLANG:
|
|
||||||
change_lang ();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case cmdSEX:
|
|
||||||
change_sex ();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case cmdFORCESIG:
|
|
||||||
toggle_forcesig ();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case cmdGENERATE:
|
|
||||||
generate_card_keys (serialnobuf);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case cmdPASSWD:
|
|
||||||
change_pin (0);
|
|
||||||
did_checkpin = 0; /* Need to reset it of course. */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case cmdQUIT:
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
case cmdNOP:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case cmdINVCMD:
|
|
||||||
default:
|
|
||||||
tty_printf ("\n");
|
|
||||||
tty_printf (_("Invalid command (try \"help\")\n"));
|
|
||||||
break;
|
|
||||||
} /* End command switch. */
|
|
||||||
} /* End of main menu loop. */
|
|
||||||
|
|
||||||
leave:
|
|
||||||
xfree (answer);
|
|
||||||
}
|
|
||||||
|
|
165
g10/cipher.c
165
g10/cipher.c
@ -1,165 +0,0 @@
|
|||||||
/* cipher.c - En-/De-ciphering filter
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "gpg.h"
|
|
||||||
#include "errors.h"
|
|
||||||
#include "iobuf.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "filter.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "status.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define MIN_PARTIAL_SIZE 512
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
write_header( cipher_filter_context_t *cfx, iobuf_t a )
|
|
||||||
{
|
|
||||||
PACKET pkt;
|
|
||||||
PKT_encrypted ed;
|
|
||||||
byte temp[18];
|
|
||||||
unsigned int blocksize;
|
|
||||||
unsigned int nprefix;
|
|
||||||
gpg_error_t rc;
|
|
||||||
|
|
||||||
blocksize = gcry_cipher_get_algo_blklen ( cfx->dek->algo );
|
|
||||||
if( blocksize < 8 || blocksize > 16 )
|
|
||||||
log_fatal("unsupported blocksize %u\n", blocksize );
|
|
||||||
|
|
||||||
memset( &ed, 0, sizeof ed );
|
|
||||||
ed.len = cfx->datalen;
|
|
||||||
ed.extralen = blocksize+2;
|
|
||||||
ed.new_ctb = !ed.len && !RFC1991;
|
|
||||||
if( cfx->dek->use_mdc ) {
|
|
||||||
ed.mdc_method = DIGEST_ALGO_SHA1;
|
|
||||||
gcry_md_open (&cfx->mdc_hash, GCRY_MD_SHA1, 0 );
|
|
||||||
if ( DBG_HASHING )
|
|
||||||
gcry_md_start_debug ( cfx->mdc_hash, "creatmdc" );
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
char buf[20];
|
|
||||||
|
|
||||||
sprintf (buf, "%d %d", ed.mdc_method, cfx->dek->algo);
|
|
||||||
write_status_text (STATUS_BEGIN_ENCRYPTION, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
init_packet( &pkt );
|
|
||||||
pkt.pkttype = cfx->dek->use_mdc? PKT_ENCRYPTED_MDC : PKT_ENCRYPTED;
|
|
||||||
pkt.pkt.encrypted = &ed;
|
|
||||||
if( build_packet( a, &pkt ))
|
|
||||||
log_bug("build_packet(ENCR_DATA) failed\n");
|
|
||||||
nprefix = blocksize;
|
|
||||||
gcry_randomize ( temp, nprefix, GCRY_STRONG_RANDOM);
|
|
||||||
temp[nprefix] = temp[nprefix-2];
|
|
||||||
temp[nprefix+1] = temp[nprefix-1];
|
|
||||||
print_cipher_algo_note( cfx->dek->algo );
|
|
||||||
rc = gcry_cipher_open (&cfx->cipher_hd, cfx->dek->algo,
|
|
||||||
GCRY_CIPHER_MODE_CFB,
|
|
||||||
GCRY_CIPHER_SECURE
|
|
||||||
| ((cfx->dek->use_mdc || cfx->dek->algo >= 100) ?
|
|
||||||
0 : GCRY_CIPHER_ENABLE_SYNC));
|
|
||||||
if (rc) {
|
|
||||||
/* we should never get an error here cause we already checked, that
|
|
||||||
* the algorithm is available. */
|
|
||||||
BUG();
|
|
||||||
}
|
|
||||||
/* log_hexdump( "thekey", cfx->dek->key, cfx->dek->keylen );*/
|
|
||||||
gcry_cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen );
|
|
||||||
gcry_cipher_setiv( cfx->cipher_hd, NULL, 0 );
|
|
||||||
/* log_hexdump( "prefix", temp, nprefix+2 ); */
|
|
||||||
if( cfx->mdc_hash ) /* hash the "IV" */
|
|
||||||
gcry_md_write( cfx->mdc_hash, temp, nprefix+2 );
|
|
||||||
gcry_cipher_encrypt( cfx->cipher_hd, temp, nprefix+2, NULL, 0);
|
|
||||||
gcry_cipher_sync( cfx->cipher_hd );
|
|
||||||
iobuf_write(a, temp, nprefix+2);
|
|
||||||
cfx->header=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* This filter is used to en/de-cipher data with a conventional algorithm
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
cipher_filter( void *opaque, int control,
|
|
||||||
iobuf_t a, byte *buf, size_t *ret_len)
|
|
||||||
{
|
|
||||||
size_t size = *ret_len;
|
|
||||||
cipher_filter_context_t *cfx = opaque;
|
|
||||||
int rc=0;
|
|
||||||
|
|
||||||
if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */
|
|
||||||
rc = -1; /* not yet used */
|
|
||||||
}
|
|
||||||
else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
|
|
||||||
assert(a);
|
|
||||||
if( !cfx->header ) {
|
|
||||||
write_header( cfx, a );
|
|
||||||
}
|
|
||||||
if( cfx->mdc_hash )
|
|
||||||
gcry_md_write( cfx->mdc_hash, buf, size );
|
|
||||||
gcry_cipher_encrypt( cfx->cipher_hd, buf, size, NULL, 0);
|
|
||||||
rc = iobuf_write( a, buf, size );
|
|
||||||
}
|
|
||||||
else if( control == IOBUFCTRL_FREE ) {
|
|
||||||
if( cfx->mdc_hash ) {
|
|
||||||
byte *hash;
|
|
||||||
int hashlen = gcry_md_get_algo_dlen (gcry_md_get_algo (
|
|
||||||
cfx->mdc_hash));
|
|
||||||
byte temp[22];
|
|
||||||
|
|
||||||
assert( hashlen == 20 );
|
|
||||||
/* we must hash the prefix of the MDC packet here */
|
|
||||||
temp[0] = 0xd3;
|
|
||||||
temp[1] = 0x14;
|
|
||||||
gcry_md_putc ( cfx->mdc_hash, temp[0] );
|
|
||||||
gcry_md_putc ( cfx->mdc_hash, temp[1] );
|
|
||||||
|
|
||||||
gcry_md_final ( cfx->mdc_hash );
|
|
||||||
hash = gcry_md_read ( cfx->mdc_hash, 0 );
|
|
||||||
memcpy(temp+2, hash, 20);
|
|
||||||
gcry_cipher_encrypt( cfx->cipher_hd, temp, 22, NULL, 0 );
|
|
||||||
gcry_md_close ( cfx->mdc_hash ); cfx->mdc_hash = NULL;
|
|
||||||
rc = iobuf_write( a, temp, 22 );
|
|
||||||
if (rc)
|
|
||||||
log_error("writing MDC packet failed\n" );
|
|
||||||
}
|
|
||||||
gcry_cipher_close (cfx->cipher_hd);
|
|
||||||
}
|
|
||||||
else if( control == IOBUFCTRL_DESC ) {
|
|
||||||
*(char**)buf = "cipher_filter";
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
112
g10/comment.c
112
g10/comment.c
@ -1,112 +0,0 @@
|
|||||||
/* comment.c - write comment stuff
|
|
||||||
* Copyright (C) 1998, 2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "options.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "errors.h"
|
|
||||||
#include "iobuf.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "keydb.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
write_comment( iobuf_t out, const char *s )
|
|
||||||
{
|
|
||||||
PACKET pkt;
|
|
||||||
size_t n = strlen(s);
|
|
||||||
int rc=0;
|
|
||||||
|
|
||||||
pkt.pkttype = PKT_COMMENT;
|
|
||||||
if( *s != '#' ) {
|
|
||||||
pkt.pkt.comment = xmalloc ( sizeof *pkt.pkt.comment + n );
|
|
||||||
pkt.pkt.comment->len = n+1;
|
|
||||||
*pkt.pkt.comment->data = '#';
|
|
||||||
strcpy(pkt.pkt.comment->data+1, s);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pkt.pkt.comment = xmalloc ( sizeof *pkt.pkt.comment + n - 1 );
|
|
||||||
pkt.pkt.comment->len = n;
|
|
||||||
strcpy(pkt.pkt.comment->data, s);
|
|
||||||
}
|
|
||||||
if( (rc = build_packet( out, &pkt )) )
|
|
||||||
log_error("build_packet(comment) failed: %s\n", gpg_strerror (rc) );
|
|
||||||
free_packet( &pkt );
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
KBNODE
|
|
||||||
make_comment_node_from_buffer (const char *s, size_t n)
|
|
||||||
{
|
|
||||||
PACKET *pkt;
|
|
||||||
|
|
||||||
pkt = gcry_xcalloc( 1, sizeof *pkt );
|
|
||||||
pkt->pkttype = PKT_COMMENT;
|
|
||||||
pkt->pkt.comment = gcry_xmalloc( sizeof *pkt->pkt.comment + n - 1 );
|
|
||||||
pkt->pkt.comment->len = n;
|
|
||||||
strcpy(pkt->pkt.comment->data, s);
|
|
||||||
return new_kbnode( pkt );
|
|
||||||
}
|
|
||||||
|
|
||||||
KBNODE
|
|
||||||
make_comment_node( const char *s )
|
|
||||||
{
|
|
||||||
return make_comment_node_from_buffer (s, strlen (s));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
KBNODE
|
|
||||||
make_mpi_comment_node( const char *s, gcry_mpi_t a )
|
|
||||||
{
|
|
||||||
PACKET *pkt;
|
|
||||||
byte *buf, *pp;
|
|
||||||
size_t n1, nb1;
|
|
||||||
size_t n = strlen(s);
|
|
||||||
|
|
||||||
nb1 = mpi_get_nbits( a );
|
|
||||||
if (gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &n1, a))
|
|
||||||
BUG ();
|
|
||||||
/* fixme: allocate it on the stack */
|
|
||||||
buf = xmalloc (n1);
|
|
||||||
if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, n1, &n1, a))
|
|
||||||
BUG ();
|
|
||||||
|
|
||||||
pkt = xcalloc (1, sizeof *pkt );
|
|
||||||
pkt->pkttype = PKT_COMMENT;
|
|
||||||
pkt->pkt.comment = xmalloc ( sizeof *pkt->pkt.comment + n + 2 + n1 );
|
|
||||||
pkt->pkt.comment->len = n+1+2+n1;
|
|
||||||
pp = pkt->pkt.comment->data;
|
|
||||||
memcpy(pp, s, n+1);
|
|
||||||
memcpy(pp+n+1, buf, n1 );
|
|
||||||
xfree (buf);
|
|
||||||
return new_kbnode( pkt );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
329
g10/compress.c
329
g10/compress.c
@ -1,329 +0,0 @@
|
|||||||
/* compress.c - compress filter
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
|
|
||||||
* 2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <zlib.h>
|
|
||||||
#ifdef __riscos__
|
|
||||||
# include "zlib-riscos.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "gpg.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "filter.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "options.h"
|
|
||||||
|
|
||||||
static void
|
|
||||||
init_compress( compress_filter_context_t *zfx, z_stream *zs )
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
int level;
|
|
||||||
|
|
||||||
#ifdef __riscos__
|
|
||||||
static int zlib_initialized = 0;
|
|
||||||
|
|
||||||
if (!zlib_initialized)
|
|
||||||
zlib_initialized = riscos_load_module("ZLib", zlib_path, 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if( opt.compress >= 0 && opt.compress <= 9 )
|
|
||||||
level = opt.compress;
|
|
||||||
else if( opt.compress == -1 )
|
|
||||||
level = Z_DEFAULT_COMPRESSION;
|
|
||||||
else if( opt.compress == 10 ) /* remove this ! */
|
|
||||||
level = 0;
|
|
||||||
else {
|
|
||||||
log_error("invalid compression level; using default level\n");
|
|
||||||
level = Z_DEFAULT_COMPRESSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if( (rc = zfx->algo == 1? deflateInit2( zs, level, Z_DEFLATED,
|
|
||||||
-13, 8, Z_DEFAULT_STRATEGY)
|
|
||||||
: deflateInit( zs, level )
|
|
||||||
) != Z_OK ) {
|
|
||||||
log_fatal("zlib problem: %s\n", zs->msg? zs->msg :
|
|
||||||
rc == Z_MEM_ERROR ? "out of core" :
|
|
||||||
rc == Z_VERSION_ERROR ? "invalid lib version" :
|
|
||||||
"unknown error" );
|
|
||||||
}
|
|
||||||
|
|
||||||
zfx->outbufsize = 8192;
|
|
||||||
zfx->outbuf = xmalloc ( zfx->outbufsize );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, iobuf_t a )
|
|
||||||
{
|
|
||||||
gpg_error_t rc;
|
|
||||||
int zrc;
|
|
||||||
unsigned n;
|
|
||||||
|
|
||||||
do {
|
|
||||||
#ifndef __riscos__
|
|
||||||
zs->next_out = zfx->outbuf;
|
|
||||||
#else /* __riscos__ */
|
|
||||||
zs->next_out = (Bytef *) zfx->outbuf;
|
|
||||||
#endif /* __riscos__ */
|
|
||||||
zs->avail_out = zfx->outbufsize;
|
|
||||||
if( DBG_FILTER )
|
|
||||||
log_debug("enter deflate: avail_in=%u, avail_out=%u, flush=%d\n",
|
|
||||||
(unsigned)zs->avail_in, (unsigned)zs->avail_out, flush );
|
|
||||||
zrc = deflate( zs, flush );
|
|
||||||
if( zrc == Z_STREAM_END && flush == Z_FINISH )
|
|
||||||
;
|
|
||||||
else if( zrc != Z_OK ) {
|
|
||||||
if( zs->msg )
|
|
||||||
log_fatal("zlib deflate problem: %s\n", zs->msg );
|
|
||||||
else
|
|
||||||
log_fatal("zlib deflate problem: rc=%d\n", zrc );
|
|
||||||
}
|
|
||||||
n = zfx->outbufsize - zs->avail_out;
|
|
||||||
if( DBG_FILTER )
|
|
||||||
log_debug("leave deflate: "
|
|
||||||
"avail_in=%u, avail_out=%u, n=%u, zrc=%d\n",
|
|
||||||
(unsigned)zs->avail_in, (unsigned)zs->avail_out,
|
|
||||||
(unsigned)n, zrc );
|
|
||||||
|
|
||||||
rc = iobuf_write (a, zfx->outbuf, n);
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
log_debug("deflate: iobuf_write failed\n");
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
} while( zs->avail_in || (flush == Z_FINISH && zrc != Z_STREAM_END) );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
init_uncompress( compress_filter_context_t *zfx, z_stream *zs )
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* PGP uses a windowsize of 13 bits. Using a negative value for
|
|
||||||
* it forces zlib not to expect a zlib header. This is a
|
|
||||||
* undocumented feature Peter Gutmann told me about.
|
|
||||||
*
|
|
||||||
* We must use 15 bits for the inflator because CryptoEx uses 15
|
|
||||||
* bits thus the output would get scrambled w/o error indication
|
|
||||||
* if we would use 13 bits. For the uncompressing this does not
|
|
||||||
* matter at all.
|
|
||||||
*/
|
|
||||||
if( (rc = zfx->algo == 1? inflateInit2( zs, -15)
|
|
||||||
: inflateInit( zs )) != Z_OK ) {
|
|
||||||
log_fatal("zlib problem: %s\n", zs->msg? zs->msg :
|
|
||||||
rc == Z_MEM_ERROR ? "out of core" :
|
|
||||||
rc == Z_VERSION_ERROR ? "invalid lib version" :
|
|
||||||
"unknown error" );
|
|
||||||
}
|
|
||||||
|
|
||||||
zfx->inbufsize = 2048;
|
|
||||||
zfx->inbuf = xmalloc ( zfx->inbufsize );
|
|
||||||
zs->avail_in = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
do_uncompress( compress_filter_context_t *zfx, z_stream *zs,
|
|
||||||
iobuf_t a, size_t *ret_len )
|
|
||||||
{
|
|
||||||
int zrc;
|
|
||||||
int rc=0;
|
|
||||||
size_t n;
|
|
||||||
int nread, count;
|
|
||||||
int refill = !zs->avail_in;
|
|
||||||
|
|
||||||
if( DBG_FILTER )
|
|
||||||
log_debug("begin inflate: avail_in=%u, avail_out=%u, inbuf=%u\n",
|
|
||||||
(unsigned)zs->avail_in, (unsigned)zs->avail_out,
|
|
||||||
(unsigned)zfx->inbufsize );
|
|
||||||
do {
|
|
||||||
if( zs->avail_in < zfx->inbufsize && refill ) {
|
|
||||||
n = zs->avail_in;
|
|
||||||
if( !n )
|
|
||||||
#ifndef __riscos__
|
|
||||||
zs->next_in = zfx->inbuf;
|
|
||||||
#else /* __riscos__ */
|
|
||||||
zs->next_in = (Bytef *) zfx->inbuf;
|
|
||||||
#endif /* __riscos__ */
|
|
||||||
count = zfx->inbufsize - n;
|
|
||||||
nread = iobuf_read( a, zfx->inbuf + n, count );
|
|
||||||
if( nread == -1 ) nread = 0;
|
|
||||||
n += nread;
|
|
||||||
/* If we use the undocumented feature to suppress
|
|
||||||
* the zlib header, we have to give inflate an
|
|
||||||
* extra dummy byte to read */
|
|
||||||
if( nread < count && zfx->algo == 1 ) {
|
|
||||||
*(zfx->inbuf + n) = 0xFF; /* is it really needed ? */
|
|
||||||
zfx->algo1hack = 1;
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
zs->avail_in = n;
|
|
||||||
}
|
|
||||||
refill = 1;
|
|
||||||
if( DBG_FILTER )
|
|
||||||
log_debug("enter inflate: avail_in=%u, avail_out=%u\n",
|
|
||||||
(unsigned)zs->avail_in, (unsigned)zs->avail_out);
|
|
||||||
#ifdef Z_SYNC_FLUSH
|
|
||||||
zrc = inflate( zs, Z_SYNC_FLUSH );
|
|
||||||
#else
|
|
||||||
zrc = inflate( zs, Z_PARTIAL_FLUSH );
|
|
||||||
#endif
|
|
||||||
if( DBG_FILTER )
|
|
||||||
log_debug("leave inflate: avail_in=%u, avail_out=%u, zrc=%d\n",
|
|
||||||
(unsigned)zs->avail_in, (unsigned)zs->avail_out, zrc);
|
|
||||||
if( zrc == Z_STREAM_END )
|
|
||||||
rc = -1; /* eof */
|
|
||||||
else if( zrc != Z_OK && zrc != Z_BUF_ERROR ) {
|
|
||||||
if( zs->msg )
|
|
||||||
log_fatal("zlib inflate problem: %s\n", zs->msg );
|
|
||||||
else
|
|
||||||
log_fatal("zlib inflate problem: rc=%d\n", zrc );
|
|
||||||
}
|
|
||||||
} while( zs->avail_out && zrc != Z_STREAM_END && zrc != Z_BUF_ERROR );
|
|
||||||
*ret_len = zfx->outbufsize - zs->avail_out;
|
|
||||||
if( DBG_FILTER )
|
|
||||||
log_debug("do_uncompress: returning %u bytes\n", (unsigned)*ret_len );
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
compress_filter( void *opaque, int control,
|
|
||||||
iobuf_t a, byte *buf, size_t *ret_len)
|
|
||||||
{
|
|
||||||
size_t size = *ret_len;
|
|
||||||
compress_filter_context_t *zfx = opaque;
|
|
||||||
z_stream *zs = zfx->opaque;
|
|
||||||
int rc=0;
|
|
||||||
|
|
||||||
if( control == IOBUFCTRL_UNDERFLOW ) {
|
|
||||||
if( !zfx->status ) {
|
|
||||||
zs = zfx->opaque = xcalloc (1, sizeof *zs );
|
|
||||||
init_uncompress( zfx, zs );
|
|
||||||
zfx->status = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef __riscos__
|
|
||||||
zs->next_out = buf;
|
|
||||||
#else /* __riscos__ */
|
|
||||||
zs->next_out = (Bytef *) buf;
|
|
||||||
#endif /* __riscos__ */
|
|
||||||
zs->avail_out = size;
|
|
||||||
zfx->outbufsize = size; /* needed only for calculation */
|
|
||||||
rc = do_uncompress( zfx, zs, a, ret_len );
|
|
||||||
}
|
|
||||||
else if( control == IOBUFCTRL_FLUSH ) {
|
|
||||||
if( !zfx->status ) {
|
|
||||||
PACKET pkt;
|
|
||||||
PKT_compressed cd;
|
|
||||||
|
|
||||||
if( !zfx->algo )
|
|
||||||
zfx->algo = DEFAULT_COMPRESS_ALGO;
|
|
||||||
if( zfx->algo != 1 && zfx->algo != 2 )
|
|
||||||
BUG();
|
|
||||||
memset( &cd, 0, sizeof cd );
|
|
||||||
cd.len = 0;
|
|
||||||
cd.algorithm = zfx->algo;
|
|
||||||
init_packet( &pkt );
|
|
||||||
pkt.pkttype = PKT_COMPRESSED;
|
|
||||||
pkt.pkt.compressed = &cd;
|
|
||||||
if( build_packet( a, &pkt ))
|
|
||||||
log_bug("build_packet(PKT_COMPRESSED) failed\n");
|
|
||||||
zs = zfx->opaque = xcalloc (1, sizeof *zs );
|
|
||||||
init_compress( zfx, zs );
|
|
||||||
zfx->status = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef __riscos__
|
|
||||||
zs->next_in = buf;
|
|
||||||
#else /* __riscos__ */
|
|
||||||
zs->next_in = (Bytef *) buf;
|
|
||||||
#endif /* __riscos__ */
|
|
||||||
zs->avail_in = size;
|
|
||||||
rc = do_compress( zfx, zs, Z_NO_FLUSH, a );
|
|
||||||
}
|
|
||||||
else if( control == IOBUFCTRL_FREE ) {
|
|
||||||
if( zfx->status == 1 ) {
|
|
||||||
inflateEnd(zs);
|
|
||||||
xfree (zs);
|
|
||||||
zfx->opaque = NULL;
|
|
||||||
xfree (zfx->outbuf); zfx->outbuf = NULL;
|
|
||||||
}
|
|
||||||
else if( zfx->status == 2 ) {
|
|
||||||
#ifndef __riscos__
|
|
||||||
zs->next_in = buf;
|
|
||||||
#else /* __riscos__ */
|
|
||||||
zs->next_in = (Bytef *) buf;
|
|
||||||
#endif /* __riscos__ */
|
|
||||||
zs->avail_in = 0;
|
|
||||||
do_compress( zfx, zs, Z_FINISH, a );
|
|
||||||
deflateEnd(zs);
|
|
||||||
xfree (zs);
|
|
||||||
zfx->opaque = NULL;
|
|
||||||
xfree (zfx->outbuf); zfx->outbuf = NULL;
|
|
||||||
}
|
|
||||||
if (zfx->release)
|
|
||||||
zfx->release (zfx);
|
|
||||||
}
|
|
||||||
else if( control == IOBUFCTRL_DESC )
|
|
||||||
*(char**)buf = "compress_filter";
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
release_context (compress_filter_context_t *ctx)
|
|
||||||
{
|
|
||||||
xfree (ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Handle a compressed packet
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
handle_compressed( void *procctx, PKT_compressed *cd,
|
|
||||||
int (*callback)(iobuf_t, void *), void *passthru )
|
|
||||||
{
|
|
||||||
compress_filter_context_t *cfx;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if( cd->algorithm < 1 || cd->algorithm > 2 )
|
|
||||||
return GPG_ERR_COMPR_ALGO;
|
|
||||||
cfx = xcalloc (1,sizeof *cfx);
|
|
||||||
cfx->algo = cd->algorithm;
|
|
||||||
cfx->release = release_context;
|
|
||||||
iobuf_push_filter( cd->buf, compress_filter, cfx );
|
|
||||||
if( callback )
|
|
||||||
rc = callback(cd->buf, passthru );
|
|
||||||
else
|
|
||||||
rc = proc_packets(procctx, cd->buf);
|
|
||||||
cd->buf = NULL;
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
123
g10/dearmor.c
123
g10/dearmor.c
@ -1,123 +0,0 @@
|
|||||||
/* dearmor.c - Armor utility
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "gpg.h"
|
|
||||||
#include "errors.h"
|
|
||||||
#include "iobuf.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "filter.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "main.h"
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Take an armor file and write it out without armor
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
dearmor_file( const char *fname )
|
|
||||||
{
|
|
||||||
armor_filter_context_t afx;
|
|
||||||
iobuf_t inp = NULL, out = NULL;
|
|
||||||
int rc = 0;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
memset( &afx, 0, sizeof afx);
|
|
||||||
|
|
||||||
/* prepare iobufs */
|
|
||||||
if( !(inp = iobuf_open(fname)) ) {
|
|
||||||
rc = gpg_error_from_errno (errno);
|
|
||||||
log_error("can't open %s: %s\n", fname? fname: "[stdin]",
|
|
||||||
strerror(errno) );
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
iobuf_push_filter( inp, armor_filter, &afx );
|
|
||||||
|
|
||||||
if( (rc = open_outfile( fname, 0, &out )) )
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
while( (c = iobuf_get(inp)) != -1 )
|
|
||||||
iobuf_put( out, c );
|
|
||||||
|
|
||||||
|
|
||||||
leave:
|
|
||||||
if( rc )
|
|
||||||
iobuf_cancel(out);
|
|
||||||
else
|
|
||||||
iobuf_close(out);
|
|
||||||
iobuf_close(inp);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Take file and write it out with armor
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
enarmor_file( const char *fname )
|
|
||||||
{
|
|
||||||
armor_filter_context_t afx;
|
|
||||||
iobuf_t inp = NULL, out = NULL;
|
|
||||||
int rc = 0;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
memset( &afx, 0, sizeof afx);
|
|
||||||
|
|
||||||
/* prepare iobufs */
|
|
||||||
if( !(inp = iobuf_open(fname)) ) {
|
|
||||||
rc = gpg_error_from_errno (errno);
|
|
||||||
log_error("can't open %s: %s\n", fname? fname: "[stdin]",
|
|
||||||
strerror(errno) );
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if( (rc = open_outfile( fname, 1, &out )) )
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
afx.what = 4;
|
|
||||||
afx.hdrlines = "Comment: Use \"gpg --dearmor\" for unpacking\n";
|
|
||||||
iobuf_push_filter( out, armor_filter, &afx );
|
|
||||||
|
|
||||||
while( (c = iobuf_get(inp)) != -1 )
|
|
||||||
iobuf_put( out, c );
|
|
||||||
|
|
||||||
|
|
||||||
leave:
|
|
||||||
if( rc )
|
|
||||||
iobuf_cancel(out);
|
|
||||||
else
|
|
||||||
iobuf_close(out);
|
|
||||||
iobuf_close(inp);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
142
g10/decrypt.c
142
g10/decrypt.c
@ -1,142 +0,0 @@
|
|||||||
/* decrypt.c - verify signed data
|
|
||||||
* Copyright (C) 1998,1999,2000,2001,2002,2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "options.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "errors.h"
|
|
||||||
#include "iobuf.h"
|
|
||||||
#include "keydb.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "status.h"
|
|
||||||
#include "i18n.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Assume that the input is an encrypted message and decrypt
|
|
||||||
* (and if signed, verify the signature on) it.
|
|
||||||
* This command differs from the default operation, as it never
|
|
||||||
* writes to the filename which is included in the file and it
|
|
||||||
* rejects files which don't begin with an encrypted message.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
decrypt_message( const char *filename )
|
|
||||||
{
|
|
||||||
iobuf_t fp;
|
|
||||||
armor_filter_context_t afx;
|
|
||||||
progress_filter_context_t pfx;
|
|
||||||
int rc;
|
|
||||||
int no_out=0;
|
|
||||||
|
|
||||||
/* open the message file */
|
|
||||||
fp = iobuf_open(filename);
|
|
||||||
if( !fp ) {
|
|
||||||
rc = gpg_error_from_errno (errno);
|
|
||||||
log_error(_("can't open `%s'\n"), print_fname_stdin(filename));
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
handle_progress (&pfx, fp, filename);
|
|
||||||
|
|
||||||
if( !opt.no_armor ) {
|
|
||||||
if( use_armor_filter( fp ) ) {
|
|
||||||
memset( &afx, 0, sizeof afx);
|
|
||||||
iobuf_push_filter( fp, armor_filter, &afx );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !opt.outfile ) {
|
|
||||||
no_out = 1;
|
|
||||||
opt.outfile = "-";
|
|
||||||
}
|
|
||||||
rc = proc_encryption_packets( NULL, fp );
|
|
||||||
if( no_out )
|
|
||||||
opt.outfile = NULL;
|
|
||||||
iobuf_close(fp);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
decrypt_messages(int nfiles, char **files)
|
|
||||||
{
|
|
||||||
iobuf_t fp;
|
|
||||||
armor_filter_context_t afx;
|
|
||||||
progress_filter_context_t pfx;
|
|
||||||
char *p, *output = NULL;
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
if (opt.outfile)
|
|
||||||
{
|
|
||||||
log_error(_("--output doesn't work for this command\n"));
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
while (nfiles--)
|
|
||||||
{
|
|
||||||
print_file_status(STATUS_FILE_START, *files, 3);
|
|
||||||
output = make_outfile_name(*files);
|
|
||||||
if (!output)
|
|
||||||
goto next_file;
|
|
||||||
fp = iobuf_open(*files);
|
|
||||||
if (!fp)
|
|
||||||
{
|
|
||||||
log_error(_("can't open `%s'\n"), print_fname_stdin(*files));
|
|
||||||
goto next_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
handle_progress (&pfx, fp, *files);
|
|
||||||
|
|
||||||
if (!opt.no_armor)
|
|
||||||
{
|
|
||||||
if (use_armor_filter(fp))
|
|
||||||
{
|
|
||||||
memset(&afx, 0, sizeof afx);
|
|
||||||
iobuf_push_filter(fp, armor_filter, &afx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rc = proc_packets(NULL, fp);
|
|
||||||
iobuf_close(fp);
|
|
||||||
if (rc)
|
|
||||||
log_error("%s: decryption failed: %s\n", print_fname_stdin(*files),
|
|
||||||
gpg_strerror (rc));
|
|
||||||
p = get_last_passphrase();
|
|
||||||
set_next_passphrase(p);
|
|
||||||
xfree (p);
|
|
||||||
|
|
||||||
next_file:
|
|
||||||
/* Note that we emit file_done even after an error. */
|
|
||||||
write_status( STATUS_FILE_DONE );
|
|
||||||
xfree (output);
|
|
||||||
files++;
|
|
||||||
}
|
|
||||||
set_next_passphrase(NULL);
|
|
||||||
}
|
|
||||||
|
|
209
g10/delkey.c
209
g10/delkey.c
@ -1,209 +0,0 @@
|
|||||||
/* delkey.c - delete keys
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "options.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "errors.h"
|
|
||||||
#include "iobuf.h"
|
|
||||||
#include "keydb.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "trustdb.h"
|
|
||||||
#include "filter.h"
|
|
||||||
#include "ttyio.h"
|
|
||||||
#include "status.h"
|
|
||||||
#include "i18n.h"
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Delete a public or secret key from a keyring.
|
|
||||||
* r_sec_avail will be set if a secret key is available and the public
|
|
||||||
* key can't be deleted for that reason.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
do_delete_key( const char *username, int secret, int *r_sec_avail )
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
KBNODE keyblock = NULL;
|
|
||||||
KBNODE node;
|
|
||||||
KEYDB_HANDLE hd = keydb_new (secret);
|
|
||||||
PKT_public_key *pk = NULL;
|
|
||||||
PKT_secret_key *sk = NULL;
|
|
||||||
u32 keyid[2];
|
|
||||||
int okay=0;
|
|
||||||
int yes;
|
|
||||||
KEYDB_SEARCH_DESC desc;
|
|
||||||
int exactmatch;
|
|
||||||
|
|
||||||
*r_sec_avail = 0;
|
|
||||||
|
|
||||||
/* search the userid */
|
|
||||||
classify_user_id (username, &desc);
|
|
||||||
exactmatch = (desc.mode == KEYDB_SEARCH_MODE_FPR
|
|
||||||
|| desc.mode == KEYDB_SEARCH_MODE_FPR16
|
|
||||||
|| desc.mode == KEYDB_SEARCH_MODE_FPR20);
|
|
||||||
rc = desc.mode? keydb_search (hd, &desc, 1):GPG_ERR_INV_USER_ID;
|
|
||||||
if (rc) {
|
|
||||||
log_error (_("key `%s' not found: %s\n"), username, gpg_strerror (rc));
|
|
||||||
write_status_text( STATUS_DELETE_PROBLEM, "1" );
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* read the keyblock */
|
|
||||||
rc = keydb_get_keyblock (hd, &keyblock );
|
|
||||||
if (rc) {
|
|
||||||
log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) );
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the keyid from the keyblock */
|
|
||||||
node = find_kbnode( keyblock, secret? PKT_SECRET_KEY:PKT_PUBLIC_KEY );
|
|
||||||
if( !node ) {
|
|
||||||
log_error("Oops; key not found anymore!\n");
|
|
||||||
rc = GPG_ERR_GENERAL;
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( secret ) {
|
|
||||||
sk = node->pkt->pkt.secret_key;
|
|
||||||
keyid_from_sk( sk, keyid );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pk = node->pkt->pkt.public_key;
|
|
||||||
keyid_from_pk( pk, keyid );
|
|
||||||
rc = seckey_available( keyid );
|
|
||||||
if( !rc ) {
|
|
||||||
*r_sec_avail = 1;
|
|
||||||
rc = -1;
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
else if( rc != GPG_ERR_NO_SECKEY ) {
|
|
||||||
log_error("%s: get secret key: %s\n", username, gpg_strerror (rc) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rc = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( rc )
|
|
||||||
rc = 0;
|
|
||||||
else if (opt.batch && exactmatch)
|
|
||||||
okay++;
|
|
||||||
else if( opt.batch && secret )
|
|
||||||
{
|
|
||||||
log_error(_("can't do that in batchmode\n"));
|
|
||||||
log_info (_("(unless you specify the key by fingerprint)\n"));
|
|
||||||
}
|
|
||||||
else if( opt.batch && opt.answer_yes )
|
|
||||||
okay++;
|
|
||||||
else if( opt.batch )
|
|
||||||
{
|
|
||||||
log_error(_("can't do that in batchmode without \"--yes\"\n"));
|
|
||||||
log_info (_("(unless you specify the key by fingerprint)\n"));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if( secret )
|
|
||||||
print_seckey_info( sk );
|
|
||||||
else
|
|
||||||
print_pubkey_info (NULL, pk );
|
|
||||||
tty_printf( "\n" );
|
|
||||||
|
|
||||||
yes = cpr_get_answer_is_yes( secret? "delete_key.secret.okay"
|
|
||||||
: "delete_key.okay",
|
|
||||||
_("Delete this key from the keyring? "));
|
|
||||||
if( !cpr_enabled() && secret && yes ) {
|
|
||||||
/* I think it is not required to check a passphrase; if
|
|
||||||
* the user is so stupid as to let others access his secret keyring
|
|
||||||
* (and has no backup) - it is up him to read some very
|
|
||||||
* basic texts about security.
|
|
||||||
*/
|
|
||||||
yes = cpr_get_answer_is_yes("delete_key.secret.okay",
|
|
||||||
_("This is a secret key! - really delete? "));
|
|
||||||
}
|
|
||||||
if( yes )
|
|
||||||
okay++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if( okay ) {
|
|
||||||
rc = keydb_delete_keyblock (hd);
|
|
||||||
if (rc) {
|
|
||||||
log_error (_("deleting keyblock failed: %s\n"), gpg_strerror (rc) );
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note that the ownertrust being cleared will trigger a
|
|
||||||
revalidation_mark(). This makes sense - only deleting keys
|
|
||||||
that have ownertrust set should trigger this. */
|
|
||||||
|
|
||||||
if (!secret && pk && clear_ownertrusts (pk)) {
|
|
||||||
if (opt.verbose)
|
|
||||||
log_info (_("ownertrust information cleared\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
leave:
|
|
||||||
keydb_release (hd);
|
|
||||||
release_kbnode (keyblock);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Delete a public or secret key from a keyring.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
delete_keys( STRLIST names, int secret, int allow_both )
|
|
||||||
{
|
|
||||||
int rc, avail;
|
|
||||||
|
|
||||||
for(;names;names=names->next) {
|
|
||||||
rc = do_delete_key (names->d, secret, &avail );
|
|
||||||
if ( rc && avail ) {
|
|
||||||
if ( allow_both ) {
|
|
||||||
rc = do_delete_key (names->d, 1, &avail );
|
|
||||||
if ( !rc )
|
|
||||||
rc = do_delete_key (names->d, 0, &avail );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log_error(_(
|
|
||||||
"there is a secret key for public key \"%s\"!\n"),names->d);
|
|
||||||
log_info(_(
|
|
||||||
"use option \"--delete-secret-keys\" to delete it first.\n"));
|
|
||||||
write_status_text( STATUS_DELETE_PROBLEM, "2" );
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(rc) {
|
|
||||||
log_error("%s: delete key failed: %s\n", names->d, gpg_strerror (rc) );
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
821
g10/encode.c
821
g10/encode.c
@ -1,821 +0,0 @@
|
|||||||
/* encode.c - encode data
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
|
|
||||||
* 2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "gpg.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "errors.h"
|
|
||||||
#include "iobuf.h"
|
|
||||||
#include "keydb.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "filter.h"
|
|
||||||
#include "trustdb.h"
|
|
||||||
#include "i18n.h"
|
|
||||||
#include "status.h"
|
|
||||||
#include "pkglue.h"
|
|
||||||
|
|
||||||
|
|
||||||
static int encode_simple( const char *filename, int mode, int compat );
|
|
||||||
static int write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, iobuf_t out );
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Encode FILENAME with only the symmetric cipher. Take input from
|
|
||||||
* stdin if FILENAME is NULL.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
encode_symmetric( const char *filename )
|
|
||||||
{
|
|
||||||
int compat = 1;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* We don't want to use it because older gnupg version can't
|
|
||||||
handle it and we can presume that a lot of scripts are running
|
|
||||||
with the expert mode set. Some time in the future we might
|
|
||||||
want to allow for it. */
|
|
||||||
if ( opt.expert )
|
|
||||||
compat = 0; /* PGP knows how to handle this mode. */
|
|
||||||
#endif
|
|
||||||
return encode_simple( filename, 1, compat );
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Encode FILENAME as a literal data packet only. Take input from
|
|
||||||
* stdin if FILENAME is NULL.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
encode_store( const char *filename )
|
|
||||||
{
|
|
||||||
return encode_simple( filename, 0, 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
encode_sesskey (DEK * dek, DEK ** ret_dek, byte * enckey)
|
|
||||||
{
|
|
||||||
CIPHER_HANDLE hd;
|
|
||||||
DEK * c;
|
|
||||||
byte buf[33];
|
|
||||||
|
|
||||||
assert (dek->keylen < 32);
|
|
||||||
|
|
||||||
c = xcalloc (1, sizeof *c);
|
|
||||||
c->keylen = dek->keylen;
|
|
||||||
c->algo = dek->algo;
|
|
||||||
make_session_key (c);
|
|
||||||
/*log_hexdump ("thekey", c->key, c->keylen);*/
|
|
||||||
|
|
||||||
/* the encrypted session key is prefixed with a one-octet algorithm id */
|
|
||||||
buf[0] = c->algo;
|
|
||||||
memcpy (buf + 1, c->key, c->keylen);
|
|
||||||
|
|
||||||
/* due to the fact that we use only checked values, consider each
|
|
||||||
failure as fatal. */
|
|
||||||
if (gcry_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1))
|
|
||||||
BUG();
|
|
||||||
if (gcry_cipher_setkey (hd, dek->key, dek->keylen))
|
|
||||||
BUG();
|
|
||||||
gcry_cipher_setiv (hd, NULL, 0);
|
|
||||||
gcry_cipher_encrypt (hd, buf, c->keylen + 1, NULL, 0);
|
|
||||||
gcry_cipher_close (hd);
|
|
||||||
|
|
||||||
memcpy (enckey, buf, c->keylen + 1);
|
|
||||||
wipememory (buf, sizeof buf); /* burn key */
|
|
||||||
*ret_dek = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We try very hard to use a MDC */
|
|
||||||
static int
|
|
||||||
use_mdc (PK_LIST pk_list,int algo)
|
|
||||||
{
|
|
||||||
byte cipher_algid[4] = {
|
|
||||||
CIPHER_ALGO_AES,
|
|
||||||
CIPHER_ALGO_AES192,
|
|
||||||
CIPHER_ALGO_AES256,
|
|
||||||
CIPHER_ALGO_TWOFISH
|
|
||||||
};
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* RFC-1991 and 2440 don't have MDC */
|
|
||||||
if(RFC1991 || RFC2440)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* --force-mdc overrides --disable-mdc */
|
|
||||||
if (opt.force_mdc)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (opt.disable_mdc)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Do the keys really support MDC? */
|
|
||||||
|
|
||||||
if (select_mdc_from_pklist (pk_list))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* The keys don't support MDC, so now we do a bit of a hack - if any
|
|
||||||
of the AESes or TWOFISH are in the prefs, we assume that the user
|
|
||||||
can handle a MDC. This is valid for PGP 7, which can handle MDCs
|
|
||||||
though it will not generate them. 2440bis allows this, by the
|
|
||||||
way. */
|
|
||||||
for (i=0; i < DIM (cipher_algid); i++)
|
|
||||||
{
|
|
||||||
if (select_algo_from_prefs (pk_list, PREFTYPE_SYM, cipher_algid[i],
|
|
||||||
NULL) == cipher_algid[i])
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Last try. Use MDC for the modern ciphers. */
|
|
||||||
if (gcry_cipher_get_algo_blklen (algo) != 8)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0; /* No MDC */
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
encode_simple( const char *filename, int mode, int compat )
|
|
||||||
{
|
|
||||||
iobuf_t inp, out;
|
|
||||||
PACKET pkt;
|
|
||||||
DEK *dek = NULL;
|
|
||||||
PKT_plaintext *pt = NULL;
|
|
||||||
STRING2KEY *s2k = NULL;
|
|
||||||
byte enckey[33];
|
|
||||||
int rc = 0;
|
|
||||||
int seskeylen = 0;
|
|
||||||
u32 filesize;
|
|
||||||
cipher_filter_context_t cfx;
|
|
||||||
armor_filter_context_t afx;
|
|
||||||
compress_filter_context_t zfx;
|
|
||||||
text_filter_context_t tfx;
|
|
||||||
progress_filter_context_t pfx;
|
|
||||||
int do_compress = opt.compress && !RFC1991;
|
|
||||||
|
|
||||||
memset( &cfx, 0, sizeof cfx);
|
|
||||||
memset( &afx, 0, sizeof afx);
|
|
||||||
memset( &zfx, 0, sizeof zfx);
|
|
||||||
memset( &tfx, 0, sizeof tfx);
|
|
||||||
init_packet(&pkt);
|
|
||||||
|
|
||||||
/* prepare iobufs */
|
|
||||||
if( !(inp = iobuf_open(filename)) ) {
|
|
||||||
rc = gpg_error_from_errno (errno);
|
|
||||||
log_error(_("%s: can't open: %s\n"), filename? filename: "[stdin]",
|
|
||||||
strerror(errno) );
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
handle_progress (&pfx, inp, filename);
|
|
||||||
|
|
||||||
if( opt.textmode )
|
|
||||||
iobuf_push_filter( inp, text_filter, &tfx );
|
|
||||||
|
|
||||||
/* Due the the fact that we use don't use an IV to encrypt the
|
|
||||||
session key we can't use the new mode with RFC1991 because
|
|
||||||
it has no S2K salt. RFC1991 always uses simple S2K. */
|
|
||||||
if ( RFC1991 && !compat )
|
|
||||||
compat = 1;
|
|
||||||
|
|
||||||
cfx.dek = NULL;
|
|
||||||
if( mode ) {
|
|
||||||
s2k = xcalloc (1, sizeof *s2k );
|
|
||||||
s2k->mode = RFC1991? 0:opt.s2k_mode;
|
|
||||||
s2k->hash_algo = opt.s2k_digest_algo;
|
|
||||||
cfx.dek = passphrase_to_dek( NULL, 0,
|
|
||||||
default_cipher_algo(), s2k, 2,
|
|
||||||
NULL, NULL);
|
|
||||||
if( !cfx.dek || !cfx.dek->keylen ) {
|
|
||||||
rc = gpg_error (GPG_ERR_INV_PASSPHRASE);
|
|
||||||
xfree (cfx.dek);
|
|
||||||
xfree (s2k);
|
|
||||||
iobuf_close(inp);
|
|
||||||
log_error(_("error creating passphrase: %s\n"), gpg_strerror (rc) );
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
if (!compat && s2k->mode != 1 && s2k->mode != 3) {
|
|
||||||
compat = 1;
|
|
||||||
log_info (_("can't use a symmetric ESK packet "
|
|
||||||
"due to the S2K mode\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !compat ) {
|
|
||||||
seskeylen = gcry_cipher_get_algo_keylen (default_cipher_algo());
|
|
||||||
encode_sesskey( cfx.dek, &dek, enckey );
|
|
||||||
xfree (cfx.dek); cfx.dek = dek;
|
|
||||||
}
|
|
||||||
|
|
||||||
cfx.dek->use_mdc=use_mdc(NULL,cfx.dek->algo);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt.compress == -1 && cfx.dek && cfx.dek->use_mdc &&
|
|
||||||
is_file_compressed(filename, &rc))
|
|
||||||
{
|
|
||||||
if (opt.verbose)
|
|
||||||
log_info(_("`%s' already compressed\n"), filename);
|
|
||||||
do_compress = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( rc || (rc = open_outfile( filename, opt.armor? 1:0, &out )) ) {
|
|
||||||
iobuf_cancel(inp);
|
|
||||||
xfree (cfx.dek);
|
|
||||||
xfree (s2k);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( opt.armor )
|
|
||||||
iobuf_push_filter( out, armor_filter, &afx );
|
|
||||||
#ifdef ENABLE_COMMENT_PACKETS
|
|
||||||
else {
|
|
||||||
write_comment( out, "#created by GNUPG v" VERSION " ("
|
|
||||||
PRINTABLE_OS_NAME ")");
|
|
||||||
if( opt.comment_string )
|
|
||||||
write_comment( out, opt.comment_string );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if( s2k && !RFC1991 ) {
|
|
||||||
PKT_symkey_enc *enc = xcalloc (1, sizeof *enc + seskeylen + 1 );
|
|
||||||
enc->version = 4;
|
|
||||||
enc->cipher_algo = cfx.dek->algo;
|
|
||||||
enc->s2k = *s2k;
|
|
||||||
if ( !compat && seskeylen ) {
|
|
||||||
enc->seskeylen = seskeylen + 1; /* algo id */
|
|
||||||
memcpy( enc->seskey, enckey, seskeylen + 1 );
|
|
||||||
}
|
|
||||||
pkt.pkttype = PKT_SYMKEY_ENC;
|
|
||||||
pkt.pkt.symkey_enc = enc;
|
|
||||||
if( (rc = build_packet( out, &pkt )) )
|
|
||||||
log_error("build symkey packet failed: %s\n", gpg_strerror (rc) );
|
|
||||||
xfree (enc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!opt.no_literal) {
|
|
||||||
/* setup the inner packet */
|
|
||||||
if( filename || opt.set_filename ) {
|
|
||||||
char *s = make_basename ( opt.set_filename ? opt.set_filename
|
|
||||||
: filename
|
|
||||||
/* for riscos?
|
|
||||||
.iobuf_get_real_fname( inp ) */
|
|
||||||
);
|
|
||||||
pt = xmalloc ( sizeof *pt + strlen(s) - 1 );
|
|
||||||
pt->namelen = strlen(s);
|
|
||||||
memcpy(pt->name, s, pt->namelen );
|
|
||||||
xfree (s);
|
|
||||||
}
|
|
||||||
else { /* no filename */
|
|
||||||
pt = xmalloc ( sizeof *pt - 1 );
|
|
||||||
pt->namelen = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note that PGP 5 has problems decrypting symmetrically encrypted
|
|
||||||
data if the file length is in the inner packet. It works when
|
|
||||||
only partial length headers are use. In the past, we always
|
|
||||||
used partial body length here, but since PGP 2, PGP 6, and PGP
|
|
||||||
7 need the file length, and nobody should be using PGP 5
|
|
||||||
nowadays anyway, this is now set to the file length. Note also
|
|
||||||
that this only applies to the RFC-1991 style symmetric
|
|
||||||
messages, and not the RFC-2440 style. PGP 6 and 7 work with
|
|
||||||
either partial length or fixed length with the new style
|
|
||||||
messages. */
|
|
||||||
|
|
||||||
if (filename && *filename && !(*filename == '-' && !filename[1])
|
|
||||||
&& !opt.textmode ) {
|
|
||||||
off_t tmpsize;
|
|
||||||
|
|
||||||
if ( !(tmpsize = iobuf_get_filelength(inp)) )
|
|
||||||
log_info(_("%s: WARNING: empty file\n"), filename );
|
|
||||||
/* We can't encode the length of very large files because
|
|
||||||
OpenPGP uses only 32 bit for file sizes. So if the the
|
|
||||||
size of a file is larger than 2^32 minus some bytes for
|
|
||||||
packet headers, we switch to partial length encoding. */
|
|
||||||
if ( tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
|
|
||||||
filesize = tmpsize;
|
|
||||||
else
|
|
||||||
filesize = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
|
|
||||||
|
|
||||||
if (!opt.no_literal) {
|
|
||||||
pt->timestamp = make_timestamp();
|
|
||||||
pt->mode = opt.textmode? 't' : 'b';
|
|
||||||
pt->len = filesize;
|
|
||||||
pt->new_ctb = !pt->len && !RFC1991;
|
|
||||||
pt->buf = inp;
|
|
||||||
pkt.pkttype = PKT_PLAINTEXT;
|
|
||||||
pkt.pkt.plaintext = pt;
|
|
||||||
cfx.datalen = filesize && !do_compress ? calc_packet_length( &pkt ) : 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cfx.datalen = filesize && !do_compress ? filesize : 0;
|
|
||||||
pkt.pkttype = 0;
|
|
||||||
pkt.pkt.generic = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* register the cipher filter */
|
|
||||||
if( mode )
|
|
||||||
iobuf_push_filter( out, cipher_filter, &cfx );
|
|
||||||
/* register the compress filter */
|
|
||||||
if( do_compress )
|
|
||||||
{
|
|
||||||
if (cfx.dek && cfx.dek->use_mdc)
|
|
||||||
zfx.new_ctb = 1;
|
|
||||||
zfx.algo=default_compress_algo();
|
|
||||||
iobuf_push_filter( out, compress_filter, &zfx );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* do the work */
|
|
||||||
if (!opt.no_literal) {
|
|
||||||
if( (rc = build_packet( out, &pkt )) )
|
|
||||||
log_error("build_packet failed: %s\n", gpg_strerror (rc) );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* user requested not to create a literal packet,
|
|
||||||
* so we copy the plain data */
|
|
||||||
byte copy_buffer[4096];
|
|
||||||
int bytes_copied;
|
|
||||||
while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
|
|
||||||
if ( (rc=iobuf_write(out, copy_buffer, bytes_copied))) {
|
|
||||||
log_error("copying input to output failed: %s\n", gpg_strerror (rc) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
wipememory(copy_buffer, 4096); /* burn buffer */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* finish the stuff */
|
|
||||||
iobuf_close(inp);
|
|
||||||
if (rc)
|
|
||||||
iobuf_cancel(out);
|
|
||||||
else {
|
|
||||||
iobuf_close(out); /* fixme: check returncode */
|
|
||||||
if (mode)
|
|
||||||
write_status( STATUS_END_ENCRYPTION );
|
|
||||||
}
|
|
||||||
if (pt)
|
|
||||||
pt->buf = NULL;
|
|
||||||
free_packet(&pkt);
|
|
||||||
xfree (cfx.dek);
|
|
||||||
xfree (s2k);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Encrypt the file with the given userids (or ask if none
|
|
||||||
* is supplied).
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
encode_crypt( const char *filename, STRLIST remusr )
|
|
||||||
{
|
|
||||||
iobuf_t inp = NULL, out = NULL;
|
|
||||||
PACKET pkt;
|
|
||||||
PKT_plaintext *pt = NULL;
|
|
||||||
int rc = 0, rc2 = 0;
|
|
||||||
u32 filesize;
|
|
||||||
cipher_filter_context_t cfx;
|
|
||||||
armor_filter_context_t afx;
|
|
||||||
compress_filter_context_t zfx;
|
|
||||||
text_filter_context_t tfx;
|
|
||||||
progress_filter_context_t pfx;
|
|
||||||
PK_LIST pk_list,work_list;
|
|
||||||
int do_compress = opt.compress && !RFC1991;
|
|
||||||
|
|
||||||
|
|
||||||
memset( &cfx, 0, sizeof cfx);
|
|
||||||
memset( &afx, 0, sizeof afx);
|
|
||||||
memset( &zfx, 0, sizeof zfx);
|
|
||||||
memset( &tfx, 0, sizeof tfx);
|
|
||||||
init_packet(&pkt);
|
|
||||||
|
|
||||||
if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) )
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
if(PGP2) {
|
|
||||||
for(work_list=pk_list; work_list; work_list=work_list->next)
|
|
||||||
if(!(is_RSA(work_list->pk->pubkey_algo) &&
|
|
||||||
nbits_from_pk(work_list->pk)<=2048))
|
|
||||||
{
|
|
||||||
log_info(_("you can only encrypt to RSA keys of 2048 bits or "
|
|
||||||
"less in --pgp2 mode\n"));
|
|
||||||
compliance_failure();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* prepare iobufs */
|
|
||||||
if( !(inp = iobuf_open(filename)) ) {
|
|
||||||
rc = gpg_error_from_errno (errno);
|
|
||||||
log_error(_("can't open %s: %s\n"), filename? filename: "[stdin]",
|
|
||||||
strerror(errno) );
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
else if( opt.verbose )
|
|
||||||
log_info(_("reading from `%s'\n"), filename? filename: "[stdin]");
|
|
||||||
|
|
||||||
handle_progress (&pfx, inp, filename);
|
|
||||||
|
|
||||||
if( opt.textmode )
|
|
||||||
iobuf_push_filter( inp, text_filter, &tfx );
|
|
||||||
|
|
||||||
if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) )
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
|
|
||||||
if( opt.armor )
|
|
||||||
iobuf_push_filter( out, armor_filter, &afx );
|
|
||||||
#ifdef ENABLE_COMMENT_PACKETS
|
|
||||||
else {
|
|
||||||
write_comment( out, "#created by GNUPG v" VERSION " ("
|
|
||||||
PRINTABLE_OS_NAME ")");
|
|
||||||
if( opt.comment_string )
|
|
||||||
write_comment( out, opt.comment_string );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* create a session key */
|
|
||||||
cfx.dek = xcalloc_secure (1, sizeof *cfx.dek);
|
|
||||||
if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
|
|
||||||
cfx.dek->algo = select_algo_from_prefs(pk_list,PREFTYPE_SYM,-1,NULL);
|
|
||||||
/* The only way select_algo_from_prefs can fail here is when
|
|
||||||
mixing v3 and v4 keys, as v4 keys have an implicit
|
|
||||||
preference entry for 3DES, and the pk_list cannot be empty.
|
|
||||||
In this case, use 3DES anyway as it's the safest choice -
|
|
||||||
perhaps the v3 key is being used in an OpenPGP
|
|
||||||
implementation and we know that the implementation behind
|
|
||||||
any v4 key can handle 3DES. */
|
|
||||||
if( cfx.dek->algo == -1 ) {
|
|
||||||
cfx.dek->algo = CIPHER_ALGO_3DES;
|
|
||||||
|
|
||||||
if( PGP2 ) {
|
|
||||||
log_info(_("unable to use the IDEA cipher for all of the keys "
|
|
||||||
"you are encrypting to.\n"));
|
|
||||||
compliance_failure();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(!opt.expert &&
|
|
||||||
select_algo_from_prefs(pk_list,PREFTYPE_SYM,
|
|
||||||
opt.def_cipher_algo,NULL)!=opt.def_cipher_algo)
|
|
||||||
log_info(_("forcing symmetric cipher %s (%d) "
|
|
||||||
"violates recipient preferences\n"),
|
|
||||||
gcry_cipher_algo_name (opt.def_cipher_algo),
|
|
||||||
opt.def_cipher_algo);
|
|
||||||
|
|
||||||
cfx.dek->algo = opt.def_cipher_algo;
|
|
||||||
}
|
|
||||||
|
|
||||||
cfx.dek->use_mdc=use_mdc(pk_list,cfx.dek->algo);
|
|
||||||
|
|
||||||
/* Only do the is-file-already-compressed check if we are using a
|
|
||||||
MDC. This forces compressed files to be re-compressed if we do
|
|
||||||
not have a MDC to give some protection against chosen
|
|
||||||
ciphertext attacks. */
|
|
||||||
|
|
||||||
if (opt.compress == -1 && cfx.dek->use_mdc &&
|
|
||||||
is_file_compressed(filename, &rc2) )
|
|
||||||
{
|
|
||||||
if (opt.verbose)
|
|
||||||
log_info(_("`%s' already compressed\n"), filename);
|
|
||||||
do_compress = 0;
|
|
||||||
}
|
|
||||||
if (rc2)
|
|
||||||
{
|
|
||||||
rc = rc2;
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
make_session_key( cfx.dek );
|
|
||||||
if( DBG_CIPHER )
|
|
||||||
log_printhex ("DEK is: ", cfx.dek->key, cfx.dek->keylen );
|
|
||||||
|
|
||||||
rc = write_pubkey_enc_from_list( pk_list, cfx.dek, out );
|
|
||||||
if( rc )
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
if (!opt.no_literal) {
|
|
||||||
/* setup the inner packet */
|
|
||||||
if( filename || opt.set_filename ) {
|
|
||||||
char *s = make_basename( opt.set_filename ? opt.set_filename
|
|
||||||
: filename
|
|
||||||
/* ,iobuf_get_real_fname( inp )*/ );
|
|
||||||
pt = xmalloc ( sizeof *pt + strlen(s) - 1 );
|
|
||||||
pt->namelen = strlen(s);
|
|
||||||
memcpy(pt->name, s, pt->namelen );
|
|
||||||
xfree (s);
|
|
||||||
}
|
|
||||||
else { /* no filename */
|
|
||||||
pt = xmalloc ( sizeof *pt - 1 );
|
|
||||||
pt->namelen = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filename && *filename && !(*filename == '-' && !filename[1])
|
|
||||||
&& !opt.textmode ) {
|
|
||||||
off_t tmpsize;
|
|
||||||
|
|
||||||
if ( !(tmpsize = iobuf_get_filelength(inp)) )
|
|
||||||
log_info(_("%s: WARNING: empty file\n"), filename );
|
|
||||||
/* We can't encode the length of very large files because
|
|
||||||
OpenPGP uses only 32 bit for file sizes. So if the the
|
|
||||||
size of a file is larger than 2^32 minus some bytes for
|
|
||||||
packet headers, we switch to partial length encoding. */
|
|
||||||
if ( tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
|
|
||||||
filesize = tmpsize;
|
|
||||||
else
|
|
||||||
filesize = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
|
|
||||||
|
|
||||||
if (!opt.no_literal) {
|
|
||||||
pt->timestamp = make_timestamp();
|
|
||||||
pt->mode = opt.textmode ? 't' : 'b';
|
|
||||||
pt->len = filesize;
|
|
||||||
pt->new_ctb = !pt->len && !RFC1991;
|
|
||||||
pt->buf = inp;
|
|
||||||
pkt.pkttype = PKT_PLAINTEXT;
|
|
||||||
pkt.pkt.plaintext = pt;
|
|
||||||
cfx.datalen = filesize && !do_compress? calc_packet_length( &pkt ) : 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cfx.datalen = filesize && !do_compress ? filesize : 0;
|
|
||||||
|
|
||||||
/* register the cipher filter */
|
|
||||||
iobuf_push_filter( out, cipher_filter, &cfx );
|
|
||||||
|
|
||||||
/* register the compress filter */
|
|
||||||
if( do_compress ) {
|
|
||||||
int compr_algo = opt.def_compress_algo;
|
|
||||||
|
|
||||||
if(compr_algo==-1)
|
|
||||||
{
|
|
||||||
if((compr_algo=
|
|
||||||
select_algo_from_prefs(pk_list,PREFTYPE_ZIP,-1,NULL))==-1)
|
|
||||||
compr_algo=DEFAULT_COMPRESS_ALGO;
|
|
||||||
/* Theoretically impossible to get here since uncompressed
|
|
||||||
is implicit. */
|
|
||||||
}
|
|
||||||
else if(!opt.expert &&
|
|
||||||
select_algo_from_prefs(pk_list,PREFTYPE_ZIP,
|
|
||||||
compr_algo,NULL)!=compr_algo)
|
|
||||||
log_info(_("forcing compression algorithm %s (%d) "
|
|
||||||
"violates recipient preferences\n"),
|
|
||||||
compress_algo_to_string(compr_algo),compr_algo);
|
|
||||||
|
|
||||||
/* algo 0 means no compression */
|
|
||||||
if( compr_algo )
|
|
||||||
{
|
|
||||||
if (cfx.dek && cfx.dek->use_mdc)
|
|
||||||
zfx.new_ctb = 1;
|
|
||||||
zfx.algo = compr_algo;
|
|
||||||
iobuf_push_filter( out, compress_filter, &zfx );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* do the work */
|
|
||||||
if (!opt.no_literal) {
|
|
||||||
if( (rc = build_packet( out, &pkt )) )
|
|
||||||
log_error("build_packet failed: %s\n", gpg_strerror (rc) );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* user requested not to create a literal packet, so we copy
|
|
||||||
the plain data */
|
|
||||||
byte copy_buffer[4096];
|
|
||||||
int bytes_copied;
|
|
||||||
while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
|
|
||||||
if ((rc=iobuf_write(out, copy_buffer, bytes_copied))) {
|
|
||||||
log_error("copying input to output failed: %s\n",
|
|
||||||
gpg_strerror (rc) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
wipememory(copy_buffer, 4096); /* burn buffer */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* finish the stuff */
|
|
||||||
leave:
|
|
||||||
iobuf_close(inp);
|
|
||||||
if( rc )
|
|
||||||
iobuf_cancel(out);
|
|
||||||
else {
|
|
||||||
iobuf_close(out); /* fixme: check returncode */
|
|
||||||
write_status( STATUS_END_ENCRYPTION );
|
|
||||||
}
|
|
||||||
if( pt )
|
|
||||||
pt->buf = NULL;
|
|
||||||
free_packet(&pkt);
|
|
||||||
xfree (cfx.dek);
|
|
||||||
release_pk_list( pk_list );
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Filter to do a complete public key encryption.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
encrypt_filter( void *opaque, int control,
|
|
||||||
iobuf_t a, byte *buf, size_t *ret_len)
|
|
||||||
{
|
|
||||||
size_t size = *ret_len;
|
|
||||||
encrypt_filter_context_t *efx = opaque;
|
|
||||||
int rc=0;
|
|
||||||
|
|
||||||
if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */
|
|
||||||
BUG(); /* not used */
|
|
||||||
}
|
|
||||||
else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
|
|
||||||
if( !efx->header_okay ) {
|
|
||||||
efx->cfx.dek = xcalloc_secure (1, sizeof *efx->cfx.dek );
|
|
||||||
|
|
||||||
if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
|
|
||||||
efx->cfx.dek->algo =
|
|
||||||
select_algo_from_prefs(efx->pk_list,PREFTYPE_SYM,-1,NULL);
|
|
||||||
if( efx->cfx.dek->algo == -1 ) {
|
|
||||||
/* because 3DES is implicitly in the prefs, this can only
|
|
||||||
* happen if we do not have any public keys in the list */
|
|
||||||
efx->cfx.dek->algo = DEFAULT_CIPHER_ALGO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(!opt.expert &&
|
|
||||||
select_algo_from_prefs(efx->pk_list,PREFTYPE_SYM,
|
|
||||||
opt.def_cipher_algo,
|
|
||||||
NULL)!=opt.def_cipher_algo)
|
|
||||||
log_info(_("forcing symmetric cipher %s (%d) "
|
|
||||||
"violates recipient preferences\n"),
|
|
||||||
gcry_cipher_algo_name (opt.def_cipher_algo),
|
|
||||||
opt.def_cipher_algo);
|
|
||||||
|
|
||||||
efx->cfx.dek->algo = opt.def_cipher_algo;
|
|
||||||
}
|
|
||||||
|
|
||||||
efx->cfx.dek->use_mdc = use_mdc(efx->pk_list,efx->cfx.dek->algo);
|
|
||||||
|
|
||||||
make_session_key( efx->cfx.dek );
|
|
||||||
if( DBG_CIPHER )
|
|
||||||
log_printhex ("DEK is: ",
|
|
||||||
efx->cfx.dek->key, efx->cfx.dek->keylen );
|
|
||||||
|
|
||||||
rc = write_pubkey_enc_from_list( efx->pk_list, efx->cfx.dek, a );
|
|
||||||
if( rc )
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
iobuf_push_filter( a, cipher_filter, &efx->cfx );
|
|
||||||
|
|
||||||
efx->header_okay = 1;
|
|
||||||
}
|
|
||||||
rc = iobuf_write( a, buf, size );
|
|
||||||
|
|
||||||
}
|
|
||||||
else if( control == IOBUFCTRL_FREE ) {
|
|
||||||
}
|
|
||||||
else if( control == IOBUFCTRL_DESC ) {
|
|
||||||
*(char**)buf = "encrypt_filter";
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Write pubkey-enc packets from the list of PKs to OUT.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, iobuf_t out )
|
|
||||||
{
|
|
||||||
PACKET pkt;
|
|
||||||
PKT_public_key *pk;
|
|
||||||
PKT_pubkey_enc *enc;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
for( ; pk_list; pk_list = pk_list->next ) {
|
|
||||||
gcry_mpi_t frame;
|
|
||||||
|
|
||||||
pk = pk_list->pk;
|
|
||||||
|
|
||||||
print_pubkey_algo_note( pk->pubkey_algo );
|
|
||||||
enc = xcalloc (1, sizeof *enc );
|
|
||||||
enc->pubkey_algo = pk->pubkey_algo;
|
|
||||||
keyid_from_pk( pk, enc->keyid );
|
|
||||||
enc->throw_keyid = (opt.throw_keyid || (pk_list->flags&1));
|
|
||||||
|
|
||||||
if(opt.throw_keyid && (PGP2 || PGP6 || PGP7 || PGP8))
|
|
||||||
{
|
|
||||||
log_info(_("you may not use %s while in %s mode\n"),
|
|
||||||
"--throw-keyid",compliance_option_string());
|
|
||||||
compliance_failure();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Okay, what's going on: We have the session key somewhere in
|
|
||||||
* the structure DEK and want to encode this session key in
|
|
||||||
* an integer value of n bits. pubkey_nbits gives us the
|
|
||||||
* number of bits we have to use. We then encode the session
|
|
||||||
* key in some way and we get it back in the big intger value
|
|
||||||
* FRAME. Then we use FRAME, the public key PK->PKEY and the
|
|
||||||
* algorithm number PK->PUBKEY_ALGO and pass it to pubkey_encrypt
|
|
||||||
* which returns the encrypted value in the array ENC->DATA.
|
|
||||||
* This array has a size which depends on the used algorithm
|
|
||||||
* (e.g. 2 for ElGamal). We don't need frame anymore because we
|
|
||||||
* have everything now in enc->data which is the passed to
|
|
||||||
* build_packet()
|
|
||||||
*/
|
|
||||||
frame = encode_session_key( dek, pubkey_nbits( pk->pubkey_algo,
|
|
||||||
pk->pkey ) );
|
|
||||||
rc = pk_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey );
|
|
||||||
gcry_mpi_release ( frame );
|
|
||||||
if( rc )
|
|
||||||
log_error("pubkey_encrypt failed: %s\n", gpg_strerror (rc) );
|
|
||||||
else {
|
|
||||||
if( opt.verbose ) {
|
|
||||||
char *ustr = get_user_id_string_printable (enc->keyid);
|
|
||||||
log_info(_("%s/%s encrypted for: \"%s\"\n"),
|
|
||||||
gcry_pk_algo_name (enc->pubkey_algo),
|
|
||||||
gcry_cipher_algo_name (dek->algo), ustr );
|
|
||||||
xfree (ustr);
|
|
||||||
}
|
|
||||||
/* and write it */
|
|
||||||
init_packet(&pkt);
|
|
||||||
pkt.pkttype = PKT_PUBKEY_ENC;
|
|
||||||
pkt.pkt.pubkey_enc = enc;
|
|
||||||
rc = build_packet( out, &pkt );
|
|
||||||
if( rc )
|
|
||||||
log_error("build_packet(pubkey_enc) failed: %s\n", gpg_strerror (rc));
|
|
||||||
}
|
|
||||||
free_pubkey_enc(enc);
|
|
||||||
if( rc )
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
encode_crypt_files(int nfiles, char **files, STRLIST remusr)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
if (opt.outfile)
|
|
||||||
{
|
|
||||||
log_error(_("--output doesn't work for this command\n"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!nfiles)
|
|
||||||
{
|
|
||||||
char line[2048];
|
|
||||||
unsigned int lno = 0;
|
|
||||||
while ( fgets(line, DIM(line), stdin) )
|
|
||||||
{
|
|
||||||
lno++;
|
|
||||||
if (!*line || line[strlen(line)-1] != '\n')
|
|
||||||
{
|
|
||||||
log_error("input line %u too long or missing LF\n", lno);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
line[strlen(line)-1] = '\0';
|
|
||||||
print_file_status(STATUS_FILE_START, line, 2);
|
|
||||||
if ( (rc = encode_crypt(line, remusr)) )
|
|
||||||
log_error("%s: encryption failed: %s\n",
|
|
||||||
print_fname_stdin(line), gpg_strerror (rc) );
|
|
||||||
write_status( STATUS_FILE_DONE );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (nfiles--)
|
|
||||||
{
|
|
||||||
print_file_status(STATUS_FILE_START, *files, 2);
|
|
||||||
if ( (rc = encode_crypt(*files, remusr)) )
|
|
||||||
log_error("%s: encryption failed: %s\n",
|
|
||||||
print_fname_stdin(*files), gpg_strerror (rc) );
|
|
||||||
write_status( STATUS_FILE_DONE );
|
|
||||||
files++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
269
g10/encr-data.c
269
g10/encr-data.c
@ -1,269 +0,0 @@
|
|||||||
/* encr-data.c - process an encrypted data packet
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "gpg.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "mpi.h"
|
|
||||||
#include "cipher.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "i18n.h"
|
|
||||||
|
|
||||||
|
|
||||||
static int mdc_decode_filter( void *opaque, int control, iobuf_t a,
|
|
||||||
byte *buf, size_t *ret_len);
|
|
||||||
static int decode_filter( void *opaque, int control, iobuf_t a,
|
|
||||||
byte *buf, size_t *ret_len);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CIPHER_HANDLE cipher_hd;
|
|
||||||
MD_HANDLE mdc_hash;
|
|
||||||
char defer[20];
|
|
||||||
int defer_filled;
|
|
||||||
int eof_seen;
|
|
||||||
} decode_filter_ctx_t;
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Decrypt the data, specified by ED with the key DEK.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
|
|
||||||
{
|
|
||||||
decode_filter_ctx_t dfx;
|
|
||||||
byte *p;
|
|
||||||
int rc=0, c, i;
|
|
||||||
byte temp[32];
|
|
||||||
unsigned blocksize;
|
|
||||||
unsigned nprefix;
|
|
||||||
|
|
||||||
memset( &dfx, 0, sizeof dfx );
|
|
||||||
if( opt.verbose && !dek->algo_info_printed ) {
|
|
||||||
const char *s = gcry_cipher_algo_name (dek->algo);
|
|
||||||
if (s && *s)
|
|
||||||
log_info(_("%s encrypted data\n"), s );
|
|
||||||
else
|
|
||||||
log_info(_("encrypted with unknown algorithm %d\n"), dek->algo );
|
|
||||||
dek->algo_info_printed = 1;
|
|
||||||
}
|
|
||||||
if( (rc=openpgp_cipher_test_algo(dek->algo)) )
|
|
||||||
goto leave;
|
|
||||||
blocksize = gcry_cipher_get_algo_blklen (dek->algo);
|
|
||||||
if( !blocksize || blocksize > 16 )
|
|
||||||
log_fatal("unsupported blocksize %u\n", blocksize );
|
|
||||||
nprefix = blocksize;
|
|
||||||
if( ed->len && ed->len < (nprefix+2) )
|
|
||||||
BUG();
|
|
||||||
|
|
||||||
if( ed->mdc_method ) {
|
|
||||||
gcry_md_open (&dfx.mdc_hash, ed->mdc_method, 0 );
|
|
||||||
if ( DBG_HASHING )
|
|
||||||
gcry_md_start_debug (dfx.mdc_hash, "checkmdc");
|
|
||||||
}
|
|
||||||
rc = gcry_cipher_open (&dfx.cipher_hd, dek->algo,
|
|
||||||
GCRY_CIPHER_MODE_CFB,
|
|
||||||
GCRY_CIPHER_SECURE
|
|
||||||
| ((ed->mdc_method || dek->algo >= 100)?
|
|
||||||
0 : GCRY_CIPHER_ENABLE_SYNC) );
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
/* we should never get an error here cause we already
|
|
||||||
* checked, that the algorithm is available. What about a
|
|
||||||
* flag to let the function die in this case? */
|
|
||||||
BUG();
|
|
||||||
}
|
|
||||||
/* log_hexdump( "thekey", dek->key, dek->keylen );*/
|
|
||||||
rc = gcry_cipher_setkey (dfx.cipher_hd, dek->key, dek->keylen);
|
|
||||||
if( gpg_err_code (rc) == GPG_ERR_WEAK_KEY )
|
|
||||||
log_info(_("WARNING: message was encrypted with "
|
|
||||||
"a weak key in the symmetric cipher.\n"));
|
|
||||||
else if( rc ) {
|
|
||||||
log_error("key setup failed: %s\n", gpg_strerror (rc) );
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
if (!ed->buf) {
|
|
||||||
log_error(_("problem handling encrypted packet\n"));
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
gcry_cipher_setiv (dfx.cipher_hd, NULL, 0);
|
|
||||||
|
|
||||||
if (ed->len) {
|
|
||||||
for(i=0; i < (nprefix+2) && ed->len; i++, ed->len-- ) {
|
|
||||||
if( (c=iobuf_get(ed->buf)) == -1 )
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
temp[i] = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for(i=0; i < (nprefix+2); i++ )
|
|
||||||
if( (c=iobuf_get(ed->buf)) == -1 )
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
temp[i] = c;
|
|
||||||
}
|
|
||||||
gcry_cipher_decrypt( dfx.cipher_hd, temp, nprefix+2, NULL, 0);
|
|
||||||
gcry_cipher_sync( dfx.cipher_hd );
|
|
||||||
p = temp;
|
|
||||||
/* log_hexdump( "prefix", temp, nprefix+2 ); */
|
|
||||||
if( p[nprefix-2] != p[nprefix] || p[nprefix-1] != p[nprefix+1] ) {
|
|
||||||
rc = GPG_ERR_BAD_KEY;
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( dfx.mdc_hash )
|
|
||||||
gcry_md_write( dfx.mdc_hash, temp, nprefix+2 );
|
|
||||||
|
|
||||||
if( ed->mdc_method )
|
|
||||||
iobuf_push_filter( ed->buf, mdc_decode_filter, &dfx );
|
|
||||||
else
|
|
||||||
iobuf_push_filter( ed->buf, decode_filter, &dfx );
|
|
||||||
|
|
||||||
proc_packets( procctx, ed->buf );
|
|
||||||
ed->buf = NULL;
|
|
||||||
if( ed->mdc_method && dfx.eof_seen == 2 )
|
|
||||||
rc = gpg_error (GPG_ERR_INV_PACKET);
|
|
||||||
else if( ed->mdc_method ) { /* check the mdc */
|
|
||||||
int datalen = gcry_md_get_algo_dlen (ed->mdc_method);
|
|
||||||
|
|
||||||
gcry_cipher_decrypt (dfx.cipher_hd, dfx.defer, 20, NULL, 0);
|
|
||||||
gcry_md_final ( dfx.mdc_hash );
|
|
||||||
if( datalen != 20
|
|
||||||
|| memcmp(gcry_md_read ( dfx.mdc_hash, 0 ), dfx.defer, datalen) )
|
|
||||||
rc = gpg_error (GPG_ERR_BAD_SIGNATURE);
|
|
||||||
/*log_hexdump("MDC calculated:", gcry_md_read ( dfx.mdc_hash, 0), datalen);*/
|
|
||||||
/*log_hexdump("MDC message :", dfx.defer, 20);*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
leave:
|
|
||||||
gcry_cipher_close(dfx.cipher_hd);
|
|
||||||
gcry_md_close ( dfx.mdc_hash );
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* I think we should merge this with cipher_filter */
|
|
||||||
static int
|
|
||||||
mdc_decode_filter( void *opaque, int control, iobuf_t a,
|
|
||||||
byte *buf, size_t *ret_len)
|
|
||||||
{
|
|
||||||
decode_filter_ctx_t *dfx = opaque;
|
|
||||||
size_t n, size = *ret_len;
|
|
||||||
int rc = 0;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
if( control == IOBUFCTRL_UNDERFLOW && dfx->eof_seen ) {
|
|
||||||
*ret_len = 0;
|
|
||||||
rc = -1;
|
|
||||||
}
|
|
||||||
else if( control == IOBUFCTRL_UNDERFLOW ) {
|
|
||||||
assert(a);
|
|
||||||
assert( size > 40 );
|
|
||||||
|
|
||||||
/* get at least 20 bytes and put it somewhere ahead in the buffer */
|
|
||||||
for(n=20; n < 40 ; n++ ) {
|
|
||||||
if( (c = iobuf_get(a)) == -1 )
|
|
||||||
break;
|
|
||||||
buf[n] = c;
|
|
||||||
}
|
|
||||||
if( n == 40 ) {
|
|
||||||
/* we have enough stuff - flush the deferred stuff */
|
|
||||||
/* (we have asserted that the buffer is large enough) */
|
|
||||||
if( !dfx->defer_filled ) { /* the first time */
|
|
||||||
memcpy(buf, buf+20, 20 );
|
|
||||||
n = 20;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
memcpy(buf, dfx->defer, 20 );
|
|
||||||
}
|
|
||||||
/* now fill up */
|
|
||||||
for(; n < size; n++ ) {
|
|
||||||
if( (c = iobuf_get(a)) == -1 )
|
|
||||||
break;
|
|
||||||
buf[n] = c;
|
|
||||||
}
|
|
||||||
/* move the last 20 bytes back to the defer buffer */
|
|
||||||
/* (okay, we are wasting 20 bytes of supplied buffer) */
|
|
||||||
n -= 20;
|
|
||||||
memcpy( dfx->defer, buf+n, 20 );
|
|
||||||
dfx->defer_filled = 1;
|
|
||||||
}
|
|
||||||
else if( !dfx->defer_filled ) { /* eof seen buf empty defer */
|
|
||||||
/* this is bad because there is an incomplete hash */
|
|
||||||
n -= 20;
|
|
||||||
memcpy(buf, buf+20, n );
|
|
||||||
dfx->eof_seen = 2; /* eof with incomplete hash */
|
|
||||||
}
|
|
||||||
else { /* eof seen */
|
|
||||||
memcpy(buf, dfx->defer, 20 );
|
|
||||||
n -= 20;
|
|
||||||
memcpy( dfx->defer, buf+n, 20 );
|
|
||||||
dfx->eof_seen = 1; /* normal eof */
|
|
||||||
}
|
|
||||||
|
|
||||||
if( n ) {
|
|
||||||
gcry_cipher_decrypt( dfx->cipher_hd, buf, n, NULL, 0);
|
|
||||||
gcry_md_write( dfx->mdc_hash, buf, n );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert( dfx->eof_seen );
|
|
||||||
rc = -1; /* eof */
|
|
||||||
}
|
|
||||||
*ret_len = n;
|
|
||||||
}
|
|
||||||
else if( control == IOBUFCTRL_DESC ) {
|
|
||||||
*(char**)buf = "mdc_decode_filter";
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
decode_filter( void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len)
|
|
||||||
{
|
|
||||||
decode_filter_ctx_t *fc = opaque;
|
|
||||||
size_t n, size = *ret_len;
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
if( control == IOBUFCTRL_UNDERFLOW ) {
|
|
||||||
assert(a);
|
|
||||||
n = iobuf_read( a, buf, size );
|
|
||||||
if( n == -1 ) n = 0;
|
|
||||||
if( n )
|
|
||||||
gcry_cipher_decrypt( fc->cipher_hd, buf, n, NULL, 0);
|
|
||||||
else
|
|
||||||
rc = -1; /* eof */
|
|
||||||
*ret_len = n;
|
|
||||||
}
|
|
||||||
else if( control == IOBUFCTRL_DESC ) {
|
|
||||||
*(char**)buf = "decode_filter";
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
619
g10/exec.c
619
g10/exec.c
@ -1,619 +0,0 @@
|
|||||||
/* exec.c - generic call-a-program code
|
|
||||||
* Copyright (C) 2001, 2002, 2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifndef EXEC_TEMPFILE_ONLY
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_DOSISH_SYSTEM
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include "options.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "i18n.h"
|
|
||||||
#include "iobuf.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "exec.h"
|
|
||||||
|
|
||||||
#ifdef NO_EXEC
|
|
||||||
int exec_write(struct exec_info **info,const char *program,
|
|
||||||
const char *args_in,const char *name,int writeonly,int binary)
|
|
||||||
{
|
|
||||||
log_error(_("no remote program execution supported\n"));
|
|
||||||
return GPG_ERR_GENERAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int exec_read(struct exec_info *info) { return GPG_ERR_GENERAL; }
|
|
||||||
int exec_finish(struct exec_info *info) { return GPG_ERR_GENERAL; }
|
|
||||||
int set_exec_path(const char *path,int method) { return GPG_ERR_GENERAL; }
|
|
||||||
|
|
||||||
#else /* ! NO_EXEC */
|
|
||||||
|
|
||||||
#ifndef HAVE_MKDTEMP
|
|
||||||
char *mkdtemp(char *template);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined (_WIN32)
|
|
||||||
/* This is a nicer system() for windows that waits for programs to
|
|
||||||
return before returning control to the caller. I hate helpful
|
|
||||||
computers. */
|
|
||||||
static int win_system(const char *command)
|
|
||||||
{
|
|
||||||
PROCESS_INFORMATION pi;
|
|
||||||
STARTUPINFO si;
|
|
||||||
char *string;
|
|
||||||
|
|
||||||
/* We must use a copy of the command as CreateProcess modifies this
|
|
||||||
argument. */
|
|
||||||
string=xstrdup (command);
|
|
||||||
|
|
||||||
memset(&pi,0,sizeof(pi));
|
|
||||||
memset(&si,0,sizeof(si));
|
|
||||||
si.cb=sizeof(si);
|
|
||||||
|
|
||||||
if(!CreateProcess(NULL,string,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Wait for the child to exit */
|
|
||||||
WaitForSingleObject(pi.hProcess,INFINITE);
|
|
||||||
|
|
||||||
CloseHandle(pi.hProcess);
|
|
||||||
CloseHandle(pi.hThread);
|
|
||||||
xfree (string);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* method==0 to replace current $PATH, and 1 to append to current
|
|
||||||
$PATH. */
|
|
||||||
int set_exec_path(const char *path,int method)
|
|
||||||
{
|
|
||||||
char *p,*curpath=NULL;
|
|
||||||
size_t curlen=0;
|
|
||||||
|
|
||||||
if(method==1 && (curpath=getenv("PATH")))
|
|
||||||
curlen=strlen(curpath)+1;
|
|
||||||
|
|
||||||
p=xmalloc (5+curlen+strlen(path)+1);
|
|
||||||
strcpy(p,"PATH=");
|
|
||||||
|
|
||||||
if(curpath)
|
|
||||||
{
|
|
||||||
strcat(p,curpath);
|
|
||||||
strcat(p,":");
|
|
||||||
}
|
|
||||||
|
|
||||||
strcat(p,path);
|
|
||||||
|
|
||||||
if(DBG_EXTPROG)
|
|
||||||
log_debug("set_exec_path method %d: %s\n",method,p);
|
|
||||||
|
|
||||||
/* Notice that path is never freed. That is intentional due to the
|
|
||||||
way putenv() works. This leaks a few bytes if we call
|
|
||||||
set_exec_path multiple times. */
|
|
||||||
|
|
||||||
if(putenv(p)!=0)
|
|
||||||
return GPG_ERR_GENERAL;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Makes a temp directory and filenames */
|
|
||||||
static int make_tempdir(struct exec_info *info)
|
|
||||||
{
|
|
||||||
char *tmp=opt.temp_dir,*namein=info->name,*nameout;
|
|
||||||
|
|
||||||
if(!namein)
|
|
||||||
namein=info->binary?"tempin" EXTSEP_S "bin":"tempin" EXTSEP_S "txt";
|
|
||||||
|
|
||||||
nameout=info->binary?"tempout" EXTSEP_S "bin":"tempout" EXTSEP_S "txt";
|
|
||||||
|
|
||||||
/* Make up the temp dir and files in case we need them */
|
|
||||||
|
|
||||||
if(tmp==NULL)
|
|
||||||
{
|
|
||||||
#if defined (_WIN32)
|
|
||||||
tmp=xmalloc (256);
|
|
||||||
if(GetTempPath(256,tmp)==0)
|
|
||||||
strcpy(tmp,"c:\\windows\\temp");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int len=strlen(tmp);
|
|
||||||
|
|
||||||
/* GetTempPath may return with \ on the end */
|
|
||||||
while(len>0 && tmp[len-1]=='\\')
|
|
||||||
{
|
|
||||||
tmp[len-1]='\0';
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else /* More unixish systems */
|
|
||||||
tmp=getenv("TMPDIR");
|
|
||||||
if(tmp==NULL)
|
|
||||||
{
|
|
||||||
tmp=getenv("TMP");
|
|
||||||
if(tmp==NULL)
|
|
||||||
{
|
|
||||||
#ifdef __riscos__
|
|
||||||
tmp="<Wimp$ScrapDir>.GnuPG";
|
|
||||||
mkdir(tmp,0700); /* Error checks occur later on */
|
|
||||||
#else
|
|
||||||
tmp="/tmp";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
info->tempdir=xmalloc (strlen(tmp)+strlen(DIRSEP_S)+10+1);
|
|
||||||
|
|
||||||
sprintf(info->tempdir,"%s" DIRSEP_S "gpg-XXXXXX",tmp);
|
|
||||||
|
|
||||||
#if defined (_WIN32)
|
|
||||||
xfree (tmp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(mkdtemp(info->tempdir)==NULL)
|
|
||||||
log_error(_("can't create directory `%s': %s\n"),
|
|
||||||
info->tempdir,strerror(errno));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
info->madedir=1;
|
|
||||||
|
|
||||||
info->tempfile_in=xmalloc (strlen(info->tempdir)+
|
|
||||||
strlen(DIRSEP_S)+strlen(namein)+1);
|
|
||||||
sprintf(info->tempfile_in,"%s" DIRSEP_S "%s",info->tempdir,namein);
|
|
||||||
|
|
||||||
if(!info->writeonly)
|
|
||||||
{
|
|
||||||
info->tempfile_out=xmalloc (strlen(info->tempdir)+
|
|
||||||
strlen(DIRSEP_S)+strlen(nameout)+1);
|
|
||||||
sprintf(info->tempfile_out,"%s" DIRSEP_S "%s",info->tempdir,nameout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return info->madedir?0:GPG_ERR_GENERAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Expands %i and %o in the args to the full temp files within the
|
|
||||||
temp directory. */
|
|
||||||
static int expand_args(struct exec_info *info,const char *args_in)
|
|
||||||
{
|
|
||||||
const char *ch=args_in;
|
|
||||||
unsigned int size,len;
|
|
||||||
|
|
||||||
info->use_temp_files=0;
|
|
||||||
info->keep_temp_files=0;
|
|
||||||
|
|
||||||
if(DBG_EXTPROG)
|
|
||||||
log_debug("expanding string \"%s\"\n",args_in);
|
|
||||||
|
|
||||||
size=100;
|
|
||||||
info->command=xmalloc (size);
|
|
||||||
len=0;
|
|
||||||
info->command[0]='\0';
|
|
||||||
|
|
||||||
while(*ch!='\0')
|
|
||||||
{
|
|
||||||
if(*ch=='%')
|
|
||||||
{
|
|
||||||
char *append=NULL;
|
|
||||||
|
|
||||||
ch++;
|
|
||||||
|
|
||||||
switch(*ch)
|
|
||||||
{
|
|
||||||
case 'O':
|
|
||||||
info->keep_temp_files=1;
|
|
||||||
/* fall through */
|
|
||||||
|
|
||||||
case 'o': /* out */
|
|
||||||
if(!info->madedir)
|
|
||||||
{
|
|
||||||
if(make_tempdir(info))
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
append=info->tempfile_out;
|
|
||||||
info->use_temp_files=1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'I':
|
|
||||||
info->keep_temp_files=1;
|
|
||||||
/* fall through */
|
|
||||||
|
|
||||||
case 'i': /* in */
|
|
||||||
if(!info->madedir)
|
|
||||||
{
|
|
||||||
if(make_tempdir(info))
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
append=info->tempfile_in;
|
|
||||||
info->use_temp_files=1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '%':
|
|
||||||
append="%";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(append)
|
|
||||||
{
|
|
||||||
size_t applen=strlen(append);
|
|
||||||
|
|
||||||
if(applen+len>size-1)
|
|
||||||
{
|
|
||||||
if(applen<100)
|
|
||||||
applen=100;
|
|
||||||
|
|
||||||
size+=applen;
|
|
||||||
info->command=xrealloc(info->command,size);
|
|
||||||
}
|
|
||||||
|
|
||||||
strcat(info->command,append);
|
|
||||||
len+=strlen(append);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(len==size-1) /* leave room for the \0 */
|
|
||||||
{
|
|
||||||
size+=100;
|
|
||||||
info->command=xrealloc(info->command,size);
|
|
||||||
}
|
|
||||||
|
|
||||||
info->command[len++]=*ch;
|
|
||||||
info->command[len]='\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
ch++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(DBG_EXTPROG)
|
|
||||||
log_debug("args expanded to \"%s\", use %d, keep %d\n",
|
|
||||||
info->command,info->use_temp_files,info->keep_temp_files);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
|
|
||||||
xfree (info->command);
|
|
||||||
info->command=NULL;
|
|
||||||
|
|
||||||
return GPG_ERR_GENERAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Either handles the tempfile creation, or the fork/exec. If it
|
|
||||||
returns ok, then info->tochild is a FILE * that can be written to.
|
|
||||||
The rules are: if there are no args, then it's a fork/exec/pipe.
|
|
||||||
If there are args, but no tempfiles, then it's a fork/exec/pipe via
|
|
||||||
shell -c. If there are tempfiles, then it's a system. */
|
|
||||||
|
|
||||||
int exec_write(struct exec_info **info,const char *program,
|
|
||||||
const char *args_in,const char *name,int writeonly,int binary)
|
|
||||||
{
|
|
||||||
int ret=GPG_ERR_GENERAL;
|
|
||||||
|
|
||||||
if(opt.exec_disable && !opt.no_perm_warn)
|
|
||||||
{
|
|
||||||
log_info(_("external program calls are disabled due to unsafe "
|
|
||||||
"options file permissions\n"));
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
|
|
||||||
/* There should be no way to get to this spot while still carrying
|
|
||||||
setuid privs. Just in case, bomb out if we are. */
|
|
||||||
if(getuid()!=geteuid())
|
|
||||||
BUG();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(program==NULL && args_in==NULL)
|
|
||||||
BUG();
|
|
||||||
|
|
||||||
*info=xcalloc (1,sizeof(struct exec_info));
|
|
||||||
|
|
||||||
if(name)
|
|
||||||
(*info)->name=xstrdup (name);
|
|
||||||
(*info)->binary=binary;
|
|
||||||
(*info)->writeonly=writeonly;
|
|
||||||
|
|
||||||
/* Expand the args, if any */
|
|
||||||
if(args_in && expand_args(*info,args_in))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
#ifdef EXEC_TEMPFILE_ONLY
|
|
||||||
if(!(*info)->use_temp_files)
|
|
||||||
{
|
|
||||||
log_error(_("this platform requires temp files when calling external "
|
|
||||||
"programs\n"));
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* !EXEC_TEMPFILE_ONLY */
|
|
||||||
|
|
||||||
/* If there are no args, or there are args, but no temp files, we
|
|
||||||
can use fork/exec/pipe */
|
|
||||||
if(args_in==NULL || (*info)->use_temp_files==0)
|
|
||||||
{
|
|
||||||
int to[2],from[2];
|
|
||||||
|
|
||||||
if(pipe(to)==-1)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if(pipe(from)==-1)
|
|
||||||
{
|
|
||||||
close(to[0]);
|
|
||||||
close(to[1]);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(((*info)->child=fork())==-1)
|
|
||||||
{
|
|
||||||
close(to[0]);
|
|
||||||
close(to[1]);
|
|
||||||
close(from[0]);
|
|
||||||
close(from[1]);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((*info)->child==0)
|
|
||||||
{
|
|
||||||
char *shell=getenv("SHELL");
|
|
||||||
|
|
||||||
if(shell==NULL)
|
|
||||||
shell="/bin/sh";
|
|
||||||
|
|
||||||
/* I'm the child */
|
|
||||||
|
|
||||||
/* If the program isn't going to respond back, they get to
|
|
||||||
keep their stdout/stderr */
|
|
||||||
if(!(*info)->writeonly)
|
|
||||||
{
|
|
||||||
/* implied close of STDERR */
|
|
||||||
if(dup2(STDOUT_FILENO,STDERR_FILENO)==-1)
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
/* implied close of STDOUT */
|
|
||||||
close(from[0]);
|
|
||||||
if(dup2(from[1],STDOUT_FILENO)==-1)
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* implied close of STDIN */
|
|
||||||
close(to[1]);
|
|
||||||
if(dup2(to[0],STDIN_FILENO)==-1)
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
if(args_in==NULL)
|
|
||||||
{
|
|
||||||
if(DBG_EXTPROG)
|
|
||||||
log_debug("execlp: %s\n",program);
|
|
||||||
|
|
||||||
execlp(program,program,(void *)NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(DBG_EXTPROG)
|
|
||||||
log_debug("execlp: %s -c %s\n",shell,(*info)->command);
|
|
||||||
|
|
||||||
execlp(shell,shell,"-c",(*info)->command,(void *)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we get this far the exec failed. Clean up and return. */
|
|
||||||
|
|
||||||
log_error(_("unable to execute %s \"%s\": %s\n"),
|
|
||||||
args_in==NULL?"program":"shell",
|
|
||||||
args_in==NULL?program:shell,
|
|
||||||
strerror(errno));
|
|
||||||
|
|
||||||
/* This mimics the POSIX sh behavior - 127 means "not found"
|
|
||||||
from the shell. */
|
|
||||||
if(errno==ENOENT)
|
|
||||||
_exit(127);
|
|
||||||
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* I'm the parent */
|
|
||||||
|
|
||||||
close(to[0]);
|
|
||||||
|
|
||||||
(*info)->tochild=fdopen(to[1],binary?"wb":"w");
|
|
||||||
if((*info)->tochild==NULL)
|
|
||||||
{
|
|
||||||
ret = gpg_error_from_errno (errno);
|
|
||||||
close(to[1]);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(from[1]);
|
|
||||||
|
|
||||||
(*info)->fromchild=iobuf_fdopen(from[0],"r");
|
|
||||||
if((*info)->fromchild==NULL)
|
|
||||||
{
|
|
||||||
ret = gpg_error_from_errno (errno);
|
|
||||||
close(from[0]);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fd iobufs are cached?! */
|
|
||||||
iobuf_ioctl((*info)->fromchild,3,1,NULL);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* !EXEC_TEMPFILE_ONLY */
|
|
||||||
|
|
||||||
if(DBG_EXTPROG)
|
|
||||||
log_debug("using temp file `%s'\n",(*info)->tempfile_in);
|
|
||||||
|
|
||||||
/* It's not fork/exec/pipe, so create a temp file */
|
|
||||||
(*info)->tochild=fopen((*info)->tempfile_in,binary?"wb":"w");
|
|
||||||
if((*info)->tochild==NULL)
|
|
||||||
{
|
|
||||||
ret = gpg_error_from_errno (errno);
|
|
||||||
log_error(_("can't create `%s': %s\n"),
|
|
||||||
(*info)->tempfile_in,strerror(errno));
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret=0;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int exec_read(struct exec_info *info)
|
|
||||||
{
|
|
||||||
int ret=GPG_ERR_GENERAL;
|
|
||||||
|
|
||||||
fclose(info->tochild);
|
|
||||||
info->tochild=NULL;
|
|
||||||
|
|
||||||
if(info->use_temp_files)
|
|
||||||
{
|
|
||||||
if(DBG_EXTPROG)
|
|
||||||
log_debug("system() command is %s\n",info->command);
|
|
||||||
|
|
||||||
#if defined (_WIN32)
|
|
||||||
info->progreturn=win_system(info->command);
|
|
||||||
#else
|
|
||||||
info->progreturn=system(info->command);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(info->progreturn==-1)
|
|
||||||
{
|
|
||||||
log_error(_("system error while calling external program: %s\n"),
|
|
||||||
strerror(errno));
|
|
||||||
info->progreturn=127;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(WIFEXITED) && defined(WEXITSTATUS)
|
|
||||||
if(WIFEXITED(info->progreturn))
|
|
||||||
info->progreturn=WEXITSTATUS(info->progreturn);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log_error(_("unnatural exit of external program\n"));
|
|
||||||
info->progreturn=127;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/* If we don't have the macros, do the best we can. */
|
|
||||||
info->progreturn = (info->progreturn & 0xff00) >> 8;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 127 is the magic value returned from system() to indicate
|
|
||||||
that the shell could not be executed, or from /bin/sh to
|
|
||||||
indicate that the program could not be executed. */
|
|
||||||
|
|
||||||
if(info->progreturn==127)
|
|
||||||
{
|
|
||||||
log_error(_("unable to execute external program\n"));
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!info->writeonly)
|
|
||||||
{
|
|
||||||
info->fromchild=iobuf_open(info->tempfile_out);
|
|
||||||
if(info->fromchild==NULL)
|
|
||||||
{
|
|
||||||
ret = gpg_error_from_errno (errno);
|
|
||||||
log_error(_("unable to read external program response: %s\n"),
|
|
||||||
strerror(errno));
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do not cache this iobuf on close */
|
|
||||||
iobuf_ioctl(info->fromchild,3,1,NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret=0;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int exec_finish(struct exec_info *info)
|
|
||||||
{
|
|
||||||
int ret=info->progreturn;
|
|
||||||
|
|
||||||
if(info->fromchild)
|
|
||||||
iobuf_close(info->fromchild);
|
|
||||||
|
|
||||||
if(info->tochild)
|
|
||||||
fclose(info->tochild);
|
|
||||||
|
|
||||||
#ifndef EXEC_TEMPFILE_ONLY
|
|
||||||
if(info->child>0)
|
|
||||||
{
|
|
||||||
if(waitpid(info->child,&info->progreturn,0)!=0 &&
|
|
||||||
WIFEXITED(info->progreturn))
|
|
||||||
ret=WEXITSTATUS(info->progreturn);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log_error(_("unnatural exit of external program\n"));
|
|
||||||
ret=127;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(info->madedir && !info->keep_temp_files)
|
|
||||||
{
|
|
||||||
if(info->tempfile_in)
|
|
||||||
{
|
|
||||||
if(unlink(info->tempfile_in)==-1)
|
|
||||||
log_info(_("WARNING: unable to remove tempfile (%s) `%s': %s\n"),
|
|
||||||
"in",info->tempfile_in,strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(info->tempfile_out)
|
|
||||||
{
|
|
||||||
if(unlink(info->tempfile_out)==-1)
|
|
||||||
log_info(_("WARNING: unable to remove tempfile (%s) `%s': %s\n"),
|
|
||||||
"out",info->tempfile_out,strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(rmdir(info->tempdir)==-1)
|
|
||||||
log_info(_("WARNING: unable to remove temp directory `%s': %s\n"),
|
|
||||||
info->tempdir,strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
xfree (info->command);
|
|
||||||
xfree (info->name);
|
|
||||||
xfree (info->tempdir);
|
|
||||||
xfree (info->tempfile_in);
|
|
||||||
xfree (info->tempfile_out);
|
|
||||||
xfree (info);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif /* ! NO_EXEC */
|
|
43
g10/exec.h
43
g10/exec.h
@ -1,43 +0,0 @@
|
|||||||
/* exec.h
|
|
||||||
* Copyright (C) 2001, 2002, 2003 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 _EXEC_H_
|
|
||||||
#define _EXEC_H_
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "../common/iobuf.h"
|
|
||||||
|
|
||||||
struct exec_info
|
|
||||||
{
|
|
||||||
int progreturn,binary,writeonly,madedir,use_temp_files,keep_temp_files;
|
|
||||||
pid_t child;
|
|
||||||
FILE *tochild;
|
|
||||||
iobuf_t fromchild;
|
|
||||||
char *command,*name,*tempdir,*tempfile_in,*tempfile_out;
|
|
||||||
};
|
|
||||||
|
|
||||||
int exec_write(struct exec_info **info,const char *program,
|
|
||||||
const char *args_in,const char *name,int writeonly,int binary);
|
|
||||||
int exec_read(struct exec_info *info);
|
|
||||||
int exec_finish(struct exec_info *info);
|
|
||||||
int set_exec_path(const char *path,int method);
|
|
||||||
|
|
||||||
#endif /* !_EXEC_H_ */
|
|
546
g10/export.c
546
g10/export.c
@ -1,546 +0,0 @@
|
|||||||
/* export.c
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
|
|
||||||
* 2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "options.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "errors.h"
|
|
||||||
#include "keydb.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "i18n.h"
|
|
||||||
|
|
||||||
static int do_export( STRLIST users, int secret, unsigned int options );
|
|
||||||
static int do_export_stream( iobuf_t out, STRLIST users, int secret,
|
|
||||||
KBNODE *keyblock_out, unsigned int options,
|
|
||||||
int *any );
|
|
||||||
static int build_sexp (iobuf_t out, PACKET *pkt, int *indent);
|
|
||||||
|
|
||||||
int
|
|
||||||
parse_export_options(char *str,unsigned int *options)
|
|
||||||
{
|
|
||||||
struct parse_options export_opts[]=
|
|
||||||
{
|
|
||||||
{"include-non-rfc",EXPORT_INCLUDE_NON_RFC},
|
|
||||||
{"include-local-sigs",EXPORT_INCLUDE_LOCAL_SIGS},
|
|
||||||
{"include-attributes",EXPORT_INCLUDE_ATTRIBUTES},
|
|
||||||
{"include-sensitive-revkeys",EXPORT_INCLUDE_SENSITIVE_REVKEYS},
|
|
||||||
{"sexp-format",EXPORT_SEXP_FORMAT},
|
|
||||||
{NULL,0}
|
|
||||||
/* add tags for include revoked and disabled? */
|
|
||||||
};
|
|
||||||
|
|
||||||
return parse_options(str,options,export_opts);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Export the public keys (to standard out or --output).
|
|
||||||
* Depending on opt.armor the output is armored.
|
|
||||||
* options are defined in main.h.
|
|
||||||
* If USERS is NULL, the complete ring will be exported. */
|
|
||||||
int
|
|
||||||
export_pubkeys( STRLIST users, unsigned int options )
|
|
||||||
{
|
|
||||||
return do_export( users, 0, options );
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Export to an already opened stream; return -1 if no keys have
|
|
||||||
* been exported
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
export_pubkeys_stream( iobuf_t out, STRLIST users,
|
|
||||||
KBNODE *keyblock_out, unsigned int options )
|
|
||||||
{
|
|
||||||
int any, rc;
|
|
||||||
|
|
||||||
rc = do_export_stream( out, users, 0, keyblock_out, options, &any );
|
|
||||||
if( !rc && !any )
|
|
||||||
rc = -1;
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
export_seckeys( STRLIST users )
|
|
||||||
{
|
|
||||||
/* Use only relevant options for the secret key. */
|
|
||||||
unsigned int options = (opt.export_options & EXPORT_SEXP_FORMAT);
|
|
||||||
return do_export (users, 1, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
export_secsubkeys( STRLIST users )
|
|
||||||
{
|
|
||||||
/* Use only relevant options for the secret key. */
|
|
||||||
unsigned int options = (opt.export_options & EXPORT_SEXP_FORMAT);
|
|
||||||
return do_export( users, 2, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
do_export (STRLIST users, int secret, unsigned int options)
|
|
||||||
{
|
|
||||||
iobuf_t out = NULL;
|
|
||||||
int any, rc;
|
|
||||||
armor_filter_context_t afx;
|
|
||||||
compress_filter_context_t zfx;
|
|
||||||
|
|
||||||
memset (&afx, 0, sizeof afx);
|
|
||||||
memset (&zfx, 0, sizeof zfx);
|
|
||||||
|
|
||||||
rc = open_outfile (NULL, 0, &out);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
if (!(options & EXPORT_SEXP_FORMAT))
|
|
||||||
{
|
|
||||||
if (opt.armor)
|
|
||||||
{
|
|
||||||
afx.what = secret?5:1;
|
|
||||||
iobuf_push_filter( out, armor_filter, &afx );
|
|
||||||
}
|
|
||||||
if (opt.compress_keys && opt.compress)
|
|
||||||
iobuf_push_filter( out, compress_filter, &zfx );
|
|
||||||
}
|
|
||||||
rc = do_export_stream (out, users, secret, NULL, options, &any );
|
|
||||||
|
|
||||||
if (rc || !any)
|
|
||||||
iobuf_cancel (out);
|
|
||||||
else
|
|
||||||
iobuf_close (out);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* If keyblock_out is non-NULL, AND the exit code is zero, then it
|
|
||||||
contains a pointer to the first keyblock found and exported. No
|
|
||||||
other keyblocks are exported. The caller must free it. */
|
|
||||||
static int
|
|
||||||
do_export_stream( iobuf_t out, STRLIST users, int secret,
|
|
||||||
KBNODE *keyblock_out, unsigned int options, int *any )
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
PACKET pkt;
|
|
||||||
KBNODE keyblock = NULL;
|
|
||||||
KBNODE kbctx, node;
|
|
||||||
size_t ndesc, descindex;
|
|
||||||
KEYDB_SEARCH_DESC *desc = NULL;
|
|
||||||
KEYDB_HANDLE kdbhd;
|
|
||||||
STRLIST sl;
|
|
||||||
int indent = 0;
|
|
||||||
|
|
||||||
*any = 0;
|
|
||||||
init_packet( &pkt );
|
|
||||||
kdbhd = keydb_new (secret);
|
|
||||||
|
|
||||||
if (!users) {
|
|
||||||
ndesc = 1;
|
|
||||||
desc = xcalloc (1, ndesc * sizeof *desc);
|
|
||||||
desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
|
|
||||||
;
|
|
||||||
desc = xmalloc ( ndesc * sizeof *desc);
|
|
||||||
|
|
||||||
for (ndesc=0, sl=users; sl; sl = sl->next) {
|
|
||||||
if (classify_user_id (sl->d, desc+ndesc))
|
|
||||||
ndesc++;
|
|
||||||
else
|
|
||||||
log_error (_("key `%s' not found: %s\n"),
|
|
||||||
sl->d, gpg_strerror (GPG_ERR_INV_USER_ID));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* it would be nice to see which of the given users did
|
|
||||||
actually match one in the keyring. To implement this we
|
|
||||||
need to have a found flag for each entry in desc and to set
|
|
||||||
this we must check all those entries after a match to mark
|
|
||||||
all matched one - currently we stop at the first match. To
|
|
||||||
do this we need an extra flag to enable this feature so */
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!(rc = keydb_search2 (kdbhd, desc, ndesc, &descindex))) {
|
|
||||||
int sha1_warned=0,skip_until_subkey=0;
|
|
||||||
u32 sk_keyid[2];
|
|
||||||
|
|
||||||
if (!users)
|
|
||||||
desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
|
|
||||||
|
|
||||||
/* read the keyblock */
|
|
||||||
rc = keydb_get_keyblock (kdbhd, &keyblock );
|
|
||||||
if( rc ) {
|
|
||||||
log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) );
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* do not export keys which are incompatible with rfc2440 */
|
|
||||||
if( !(options&EXPORT_INCLUDE_NON_RFC) &&
|
|
||||||
(node = find_kbnode( keyblock, PKT_PUBLIC_KEY )) ) {
|
|
||||||
PKT_public_key *pk = node->pkt->pkt.public_key;
|
|
||||||
if( pk->version == 3 && pk->pubkey_algo > 3 ) {
|
|
||||||
log_info(_("key %08lX: not a rfc2440 key - skipped\n"),
|
|
||||||
(ulong)keyid_from_pk( pk, NULL) );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
node=find_kbnode( keyblock, PKT_SECRET_KEY );
|
|
||||||
if(node)
|
|
||||||
{
|
|
||||||
PKT_secret_key *sk=node->pkt->pkt.secret_key;
|
|
||||||
|
|
||||||
keyid_from_sk(sk,sk_keyid);
|
|
||||||
|
|
||||||
/* we can't apply GNU mode 1001 on an unprotected key */
|
|
||||||
if( secret == 2 && !sk->is_protected )
|
|
||||||
{
|
|
||||||
log_info(_("key %08lX: not protected - skipped\n"),
|
|
||||||
(ulong)sk_keyid[1]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no v3 keys with GNU mode 1001 */
|
|
||||||
if( secret == 2 && sk->version == 3 )
|
|
||||||
{
|
|
||||||
log_info(_("key %08lX: PGP 2.x style key - skipped\n"),
|
|
||||||
(ulong)sk_keyid[1]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* and write it */
|
|
||||||
for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) {
|
|
||||||
if( skip_until_subkey )
|
|
||||||
{
|
|
||||||
if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY
|
|
||||||
|| node->pkt->pkttype==PKT_SECRET_SUBKEY)
|
|
||||||
skip_until_subkey=0;
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* don't export any comment packets but those in the
|
|
||||||
* secret keyring */
|
|
||||||
if( !secret && node->pkt->pkttype == PKT_COMMENT )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* make sure that ring_trust packets never get exported */
|
|
||||||
if (node->pkt->pkttype == PKT_RING_TRUST)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* If exact is set, then we only export what was requested
|
|
||||||
(plus the primary key, if the user didn't specifically
|
|
||||||
request it) */
|
|
||||||
if(desc[descindex].exact
|
|
||||||
&& (node->pkt->pkttype==PKT_PUBLIC_SUBKEY
|
|
||||||
|| node->pkt->pkttype==PKT_SECRET_SUBKEY))
|
|
||||||
{
|
|
||||||
u32 kid[2];
|
|
||||||
byte fpr[MAX_FINGERPRINT_LEN];
|
|
||||||
size_t fprlen;
|
|
||||||
|
|
||||||
switch(desc[descindex].mode)
|
|
||||||
{
|
|
||||||
case KEYDB_SEARCH_MODE_SHORT_KID:
|
|
||||||
case KEYDB_SEARCH_MODE_LONG_KID:
|
|
||||||
if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY)
|
|
||||||
keyid_from_pk(node->pkt->pkt.public_key,kid);
|
|
||||||
else
|
|
||||||
keyid_from_sk(node->pkt->pkt.secret_key,kid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case KEYDB_SEARCH_MODE_FPR16:
|
|
||||||
case KEYDB_SEARCH_MODE_FPR20:
|
|
||||||
case KEYDB_SEARCH_MODE_FPR:
|
|
||||||
if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY)
|
|
||||||
fingerprint_from_pk(node->pkt->pkt.public_key,
|
|
||||||
fpr,&fprlen);
|
|
||||||
else
|
|
||||||
fingerprint_from_sk(node->pkt->pkt.secret_key,
|
|
||||||
fpr,&fprlen);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(desc[descindex].mode)
|
|
||||||
{
|
|
||||||
case KEYDB_SEARCH_MODE_SHORT_KID:
|
|
||||||
if (desc[descindex].u.kid[1] != kid[1])
|
|
||||||
skip_until_subkey=1;
|
|
||||||
break;
|
|
||||||
case KEYDB_SEARCH_MODE_LONG_KID:
|
|
||||||
if (desc[descindex].u.kid[0] != kid[0]
|
|
||||||
|| desc[descindex].u.kid[1] != kid[1])
|
|
||||||
skip_until_subkey=1;
|
|
||||||
break;
|
|
||||||
case KEYDB_SEARCH_MODE_FPR16:
|
|
||||||
if (memcmp (desc[descindex].u.fpr, fpr, 16))
|
|
||||||
skip_until_subkey=1;
|
|
||||||
break;
|
|
||||||
case KEYDB_SEARCH_MODE_FPR20:
|
|
||||||
case KEYDB_SEARCH_MODE_FPR:
|
|
||||||
if (memcmp (desc[descindex].u.fpr, fpr, 20))
|
|
||||||
skip_until_subkey=1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(skip_until_subkey)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( node->pkt->pkttype == PKT_SIGNATURE ) {
|
|
||||||
/* do not export packets which are marked as not exportable */
|
|
||||||
if( !(options&EXPORT_INCLUDE_LOCAL_SIGS) &&
|
|
||||||
!node->pkt->pkt.signature->flags.exportable )
|
|
||||||
continue; /* not exportable */
|
|
||||||
|
|
||||||
/* Do not export packets with a "sensitive" revocation
|
|
||||||
key unless the user wants us to. Note that we do
|
|
||||||
export these when issuing the actual revocation (see
|
|
||||||
revoke.c). */
|
|
||||||
if( !(options&EXPORT_INCLUDE_SENSITIVE_REVKEYS) &&
|
|
||||||
node->pkt->pkt.signature->revkey ) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i=0;i<node->pkt->pkt.signature->numrevkeys;i++)
|
|
||||||
if(node->pkt->pkt.signature->revkey[i]->class & 0x40)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if(i<node->pkt->pkt.signature->numrevkeys)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't export attribs? */
|
|
||||||
if( !(options&EXPORT_INCLUDE_ATTRIBUTES) &&
|
|
||||||
node->pkt->pkttype == PKT_USER_ID &&
|
|
||||||
node->pkt->pkt.user_id->attrib_data ) {
|
|
||||||
/* Skip until we get to something that is not an attrib
|
|
||||||
or a signature on an attrib */
|
|
||||||
while(kbctx->next && kbctx->next->pkt->pkttype==PKT_SIGNATURE) {
|
|
||||||
kbctx=kbctx->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY ) {
|
|
||||||
/* we don't want to export the secret parts of the
|
|
||||||
* primary key, this is done by using GNU protection mode 1001
|
|
||||||
*/
|
|
||||||
int save_mode = node->pkt->pkt.secret_key->protect.s2k.mode;
|
|
||||||
node->pkt->pkt.secret_key->protect.s2k.mode = 1001;
|
|
||||||
if ((options&EXPORT_SEXP_FORMAT))
|
|
||||||
rc = build_sexp (out, node->pkt, &indent);
|
|
||||||
else
|
|
||||||
rc = build_packet (out, node->pkt);
|
|
||||||
node->pkt->pkt.secret_key->protect.s2k.mode = save_mode;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Warn the user if the secret key or any of the secret
|
|
||||||
subkeys are protected with SHA1 and we have
|
|
||||||
simple_sk_checksum set. */
|
|
||||||
if(!sha1_warned && opt.simple_sk_checksum &&
|
|
||||||
(node->pkt->pkttype==PKT_SECRET_KEY ||
|
|
||||||
node->pkt->pkttype==PKT_SECRET_SUBKEY) &&
|
|
||||||
node->pkt->pkt.secret_key->protect.sha1chk)
|
|
||||||
{
|
|
||||||
/* I hope this warning doesn't confuse people. */
|
|
||||||
log_info(_("WARNING: secret key %08lX does not have a "
|
|
||||||
"simple SK checksum\n"),(ulong)sk_keyid[1]);
|
|
||||||
|
|
||||||
sha1_warned=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((options&EXPORT_SEXP_FORMAT))
|
|
||||||
rc = build_sexp (out, node->pkt, &indent);
|
|
||||||
else
|
|
||||||
rc = build_packet (out, node->pkt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( rc ) {
|
|
||||||
log_error("build_packet(%d) failed: %s\n",
|
|
||||||
node->pkt->pkttype, gpg_strerror (rc) );
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((options&EXPORT_SEXP_FORMAT) && indent)
|
|
||||||
{
|
|
||||||
for (; indent; indent--)
|
|
||||||
iobuf_put (out, ')');
|
|
||||||
iobuf_put (out, '\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
++*any;
|
|
||||||
if(keyblock_out)
|
|
||||||
{
|
|
||||||
*keyblock_out=keyblock;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((options&EXPORT_SEXP_FORMAT) && indent)
|
|
||||||
{
|
|
||||||
for (; indent; indent--)
|
|
||||||
iobuf_put (out, ')');
|
|
||||||
iobuf_put (out, '\n');
|
|
||||||
}
|
|
||||||
if( rc == -1 )
|
|
||||||
rc = 0;
|
|
||||||
|
|
||||||
leave:
|
|
||||||
xfree (desc);
|
|
||||||
keydb_release (kdbhd);
|
|
||||||
if(rc || keyblock_out==NULL)
|
|
||||||
release_kbnode( keyblock );
|
|
||||||
if( !*any )
|
|
||||||
log_info(_("WARNING: nothing exported\n"));
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
write_sexp_line (iobuf_t out, int *indent, const char *text)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0; i < *indent; i++)
|
|
||||||
iobuf_put (out, ' ');
|
|
||||||
iobuf_writestr (out, text);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
write_sexp_keyparm (iobuf_t out, int *indent, const char *name, gcry_mpi_t a)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
unsigned char *buffer;
|
|
||||||
|
|
||||||
write_sexp_line (out, indent, "(");
|
|
||||||
iobuf_writestr (out, name);
|
|
||||||
iobuf_writestr (out, " #");
|
|
||||||
|
|
||||||
rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, a);
|
|
||||||
assert (!rc);
|
|
||||||
iobuf_writestr (out, buffer);
|
|
||||||
iobuf_writestr (out, "#)");
|
|
||||||
gcry_free (buffer);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent)
|
|
||||||
{
|
|
||||||
PKT_secret_key *sk = pkt->pkt.secret_key;
|
|
||||||
char tmpbuf[100];
|
|
||||||
|
|
||||||
if (pkt->pkttype == PKT_SECRET_KEY)
|
|
||||||
{
|
|
||||||
iobuf_writestr (out, "(openpgp-key\n");
|
|
||||||
(*indent)++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iobuf_writestr (out, " (subkey\n");
|
|
||||||
(*indent)++;
|
|
||||||
}
|
|
||||||
(*indent)++;
|
|
||||||
write_sexp_line (out, indent, "(private-key\n");
|
|
||||||
(*indent)++;
|
|
||||||
if (is_RSA (sk->pubkey_algo) && !sk->is_protected)
|
|
||||||
{
|
|
||||||
write_sexp_line (out, indent, "(rsa\n");
|
|
||||||
(*indent)++;
|
|
||||||
write_sexp_keyparm (out, indent, "n", sk->skey[0]); iobuf_put (out,'\n');
|
|
||||||
write_sexp_keyparm (out, indent, "e", sk->skey[1]); iobuf_put (out,'\n');
|
|
||||||
write_sexp_keyparm (out, indent, "d", sk->skey[2]); iobuf_put (out,'\n');
|
|
||||||
write_sexp_keyparm (out, indent, "p", sk->skey[3]); iobuf_put (out,'\n');
|
|
||||||
write_sexp_keyparm (out, indent, "q", sk->skey[4]); iobuf_put (out,'\n');
|
|
||||||
write_sexp_keyparm (out, indent, "u", sk->skey[5]);
|
|
||||||
iobuf_put (out,')'); iobuf_put (out,'\n');
|
|
||||||
(*indent)--;
|
|
||||||
}
|
|
||||||
else if (sk->pubkey_algo == PUBKEY_ALGO_DSA && !sk->is_protected)
|
|
||||||
{
|
|
||||||
write_sexp_line (out, indent, "(dsa\n");
|
|
||||||
(*indent)++;
|
|
||||||
write_sexp_keyparm (out, indent, "p", sk->skey[0]); iobuf_put (out,'\n');
|
|
||||||
write_sexp_keyparm (out, indent, "q", sk->skey[1]); iobuf_put (out,'\n');
|
|
||||||
write_sexp_keyparm (out, indent, "g", sk->skey[2]); iobuf_put (out,'\n');
|
|
||||||
write_sexp_keyparm (out, indent, "y", sk->skey[3]); iobuf_put (out,'\n');
|
|
||||||
write_sexp_keyparm (out, indent, "x", sk->skey[4]);
|
|
||||||
iobuf_put (out,')'); iobuf_put (out,'\n');
|
|
||||||
(*indent)--;
|
|
||||||
}
|
|
||||||
else if (is_ELGAMAL (sk->pubkey_algo) && !sk->is_protected)
|
|
||||||
{
|
|
||||||
write_sexp_line (out, indent, "(elg\n");
|
|
||||||
(*indent)++;
|
|
||||||
write_sexp_keyparm (out, indent, "p", sk->skey[0]); iobuf_put (out,'\n');
|
|
||||||
write_sexp_keyparm (out, indent, "g", sk->skey[2]); iobuf_put (out,'\n');
|
|
||||||
write_sexp_keyparm (out, indent, "y", sk->skey[3]); iobuf_put (out,'\n');
|
|
||||||
write_sexp_keyparm (out, indent, "x", sk->skey[4]);
|
|
||||||
iobuf_put (out,')'); iobuf_put (out,'\n');
|
|
||||||
(*indent)--;
|
|
||||||
}
|
|
||||||
write_sexp_line (out, indent, "(attrib\n"); (*indent)++;
|
|
||||||
sprintf (tmpbuf, "(created \"%lu\"", (unsigned long)sk->timestamp);
|
|
||||||
write_sexp_line (out, indent, tmpbuf);
|
|
||||||
iobuf_put (out,')'); (*indent)--; /* close created */
|
|
||||||
iobuf_put (out,')'); (*indent)--; /* close attrib */
|
|
||||||
iobuf_put (out,')'); (*indent)--; /* close private-key */
|
|
||||||
if (pkt->pkttype != PKT_SECRET_KEY)
|
|
||||||
iobuf_put (out,')'), (*indent)--; /* close subkey */
|
|
||||||
iobuf_put (out,'\n');
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* For some packet types we write them in a S-Exp like format. This is
|
|
||||||
still EXPERIMENTAL and subject to change. */
|
|
||||||
static int
|
|
||||||
build_sexp (iobuf_t out, PACKET *pkt, int *indent)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
switch (pkt->pkttype)
|
|
||||||
{
|
|
||||||
case PKT_SECRET_KEY:
|
|
||||||
case PKT_SECRET_SUBKEY:
|
|
||||||
rc = build_sexp_seckey (out, pkt, indent);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rc = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
155
g10/filter.h
155
g10/filter.h
@ -1,155 +0,0 @@
|
|||||||
/* filter.h
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001 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_FILTER_H
|
|
||||||
#define G10_FILTER_H
|
|
||||||
|
|
||||||
#include "types.h"
|
|
||||||
#include "cipher.h"
|
|
||||||
#include "iobuf.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
MD_HANDLE md; /* catch all */
|
|
||||||
MD_HANDLE md2; /* if we want to calculate an alternate hash */
|
|
||||||
size_t maxbuf_size;
|
|
||||||
} md_filter_context_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/* these fields may be initialized */
|
|
||||||
int what; /* what kind of armor headers to write */
|
|
||||||
int only_keyblocks; /* skip all headers but ".... key block" */
|
|
||||||
const char *hdrlines; /* write these headerlines */
|
|
||||||
|
|
||||||
/* these fileds must be initialized to zero */
|
|
||||||
int no_openpgp_data; /* output flag: "No valid OpenPGP data found" */
|
|
||||||
|
|
||||||
/* the following fields must be initialized to zero */
|
|
||||||
int inp_checked; /* set if the input has been checked */
|
|
||||||
int inp_bypass; /* set if the input is not armored */
|
|
||||||
int in_cleartext; /* clear text message */
|
|
||||||
int not_dash_escaped; /* clear text is not dash escaped */
|
|
||||||
int hashes; /* detected hash algorithms */
|
|
||||||
int faked; /* we are faking a literal data packet */
|
|
||||||
int truncated; /* number of truncated lines */
|
|
||||||
int qp_detected;
|
|
||||||
int pgp2mode;
|
|
||||||
|
|
||||||
byte *buffer; /* malloced buffer */
|
|
||||||
unsigned buffer_size; /* and size of this buffer */
|
|
||||||
unsigned buffer_len; /* used length of the buffer */
|
|
||||||
unsigned buffer_pos; /* read position */
|
|
||||||
|
|
||||||
byte radbuf[4];
|
|
||||||
int idx, idx2;
|
|
||||||
u32 crc;
|
|
||||||
|
|
||||||
int status; /* an internal state flag */
|
|
||||||
int cancel;
|
|
||||||
int any_data; /* any valid armored data seen */
|
|
||||||
int pending_lf; /* used together with faked */
|
|
||||||
} armor_filter_context_t;
|
|
||||||
|
|
||||||
struct unarmor_pump_s;
|
|
||||||
typedef struct unarmor_pump_s *UnarmorPump;
|
|
||||||
|
|
||||||
|
|
||||||
struct compress_filter_context_s {
|
|
||||||
int status;
|
|
||||||
void *opaque; /* (used for z_stream) */
|
|
||||||
byte *inbuf;
|
|
||||||
unsigned inbufsize;
|
|
||||||
byte *outbuf;
|
|
||||||
unsigned outbufsize;
|
|
||||||
int algo; /* compress algo */
|
|
||||||
int algo1hack;
|
|
||||||
int new_ctb;
|
|
||||||
void (*release)(struct compress_filter_context_s*);
|
|
||||||
};
|
|
||||||
typedef struct compress_filter_context_s compress_filter_context_t;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
DEK *dek;
|
|
||||||
u32 datalen;
|
|
||||||
CIPHER_HANDLE cipher_hd;
|
|
||||||
int header;
|
|
||||||
MD_HANDLE mdc_hash;
|
|
||||||
byte enchash[20];
|
|
||||||
int create_mdc; /* flag will be set by the cipher filter */
|
|
||||||
} cipher_filter_context_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
byte *buffer; /* malloced buffer */
|
|
||||||
unsigned buffer_size; /* and size of this buffer */
|
|
||||||
unsigned buffer_len; /* used length of the buffer */
|
|
||||||
unsigned buffer_pos; /* read position */
|
|
||||||
int truncated; /* number of truncated lines */
|
|
||||||
int not_dash_escaped;
|
|
||||||
int escape_from;
|
|
||||||
MD_HANDLE md;
|
|
||||||
int pending_lf;
|
|
||||||
int pending_esc;
|
|
||||||
} text_filter_context_t;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *what; /* description */
|
|
||||||
u32 last_time; /* last time reported */
|
|
||||||
unsigned long last; /* last amount reported */
|
|
||||||
unsigned long offset; /* current amount */
|
|
||||||
unsigned long total; /* total amount */
|
|
||||||
} progress_filter_context_t;
|
|
||||||
|
|
||||||
/* encrypt_filter_context_t defined in main.h */
|
|
||||||
|
|
||||||
/*-- mdfilter.c --*/
|
|
||||||
int md_filter( void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len);
|
|
||||||
void free_md_filter_context( md_filter_context_t *mfx );
|
|
||||||
|
|
||||||
/*-- armor.c --*/
|
|
||||||
int use_armor_filter( iobuf_t a );
|
|
||||||
int armor_filter( void *opaque, int control,
|
|
||||||
iobuf_t chain, byte *buf, size_t *ret_len);
|
|
||||||
UnarmorPump unarmor_pump_new (void);
|
|
||||||
void unarmor_pump_release (UnarmorPump x);
|
|
||||||
int unarmor_pump (UnarmorPump x, int c);
|
|
||||||
|
|
||||||
/*-- compress.c --*/
|
|
||||||
int compress_filter( void *opaque, int control,
|
|
||||||
iobuf_t chain, byte *buf, size_t *ret_len);
|
|
||||||
|
|
||||||
/*-- cipher.c --*/
|
|
||||||
int cipher_filter( void *opaque, int control,
|
|
||||||
iobuf_t chain, byte *buf, size_t *ret_len);
|
|
||||||
|
|
||||||
/*-- textfilter.c --*/
|
|
||||||
int text_filter( void *opaque, int control,
|
|
||||||
iobuf_t chain, byte *buf, size_t *ret_len);
|
|
||||||
int copy_clearsig_text( iobuf_t out, iobuf_t inp, MD_HANDLE md,
|
|
||||||
int escape_dash, int escape_from, int pgp2mode );
|
|
||||||
|
|
||||||
/*-- progress.c --*/
|
|
||||||
int progress_filter (void *opaque, int control,
|
|
||||||
iobuf_t a, byte *buf, size_t *ret_len);
|
|
||||||
void handle_progress (progress_filter_context_t *pfx,
|
|
||||||
iobuf_t inp, const char *name);
|
|
||||||
|
|
||||||
#endif /*G10_FILTER_H*/
|
|
@ -1,542 +0,0 @@
|
|||||||
/* free-packet.c - cleanup stuff for packets
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "packet.h"
|
|
||||||
#include "iobuf.h"
|
|
||||||
#include "mpi.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "cipher.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "options.h"
|
|
||||||
|
|
||||||
void
|
|
||||||
free_symkey_enc( PKT_symkey_enc *enc )
|
|
||||||
{
|
|
||||||
xfree (enc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
free_pubkey_enc( PKT_pubkey_enc *enc )
|
|
||||||
{
|
|
||||||
int n, i;
|
|
||||||
n = pubkey_get_nenc( enc->pubkey_algo );
|
|
||||||
if( !n )
|
|
||||||
mpi_release (enc->data[0]);
|
|
||||||
for(i=0; i < n; i++ )
|
|
||||||
mpi_release ( enc->data[i] );
|
|
||||||
xfree (enc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
free_seckey_enc( PKT_signature *sig )
|
|
||||||
{
|
|
||||||
int n, i;
|
|
||||||
|
|
||||||
n = pubkey_get_nsig( sig->pubkey_algo );
|
|
||||||
if( !n )
|
|
||||||
mpi_release (sig->data[0]);
|
|
||||||
for(i=0; i < n; i++ )
|
|
||||||
mpi_release ( sig->data[i] );
|
|
||||||
|
|
||||||
xfree (sig->revkey);
|
|
||||||
xfree (sig->hashed);
|
|
||||||
xfree (sig->unhashed);
|
|
||||||
xfree (sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
release_public_key_parts( PKT_public_key *pk )
|
|
||||||
{
|
|
||||||
int n, i;
|
|
||||||
n = pubkey_get_npkey( pk->pubkey_algo );
|
|
||||||
if( !n )
|
|
||||||
mpi_release (pk->pkey[0]);
|
|
||||||
for(i=0; i < n; i++ ) {
|
|
||||||
mpi_release ( pk->pkey[i] );
|
|
||||||
pk->pkey[i] = NULL;
|
|
||||||
}
|
|
||||||
if (pk->prefs) {
|
|
||||||
xfree (pk->prefs);
|
|
||||||
pk->prefs = NULL;
|
|
||||||
}
|
|
||||||
if (pk->user_id) {
|
|
||||||
free_user_id (pk->user_id);
|
|
||||||
pk->user_id = NULL;
|
|
||||||
}
|
|
||||||
if (pk->revkey) {
|
|
||||||
xfree (pk->revkey);
|
|
||||||
pk->revkey=NULL;
|
|
||||||
pk->numrevkeys=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
free_public_key( PKT_public_key *pk )
|
|
||||||
{
|
|
||||||
release_public_key_parts( pk );
|
|
||||||
xfree (pk);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static subpktarea_t *
|
|
||||||
cp_subpktarea (subpktarea_t *s )
|
|
||||||
{
|
|
||||||
subpktarea_t *d;
|
|
||||||
|
|
||||||
if( !s )
|
|
||||||
return NULL;
|
|
||||||
d = xmalloc (sizeof (*d) + s->size - 1 );
|
|
||||||
d->size = s->size;
|
|
||||||
d->len = s->len;
|
|
||||||
memcpy (d->data, s->data, s->len);
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return a copy of the preferences
|
|
||||||
*/
|
|
||||||
prefitem_t *
|
|
||||||
copy_prefs (const prefitem_t *prefs)
|
|
||||||
{
|
|
||||||
size_t n;
|
|
||||||
prefitem_t *new;
|
|
||||||
|
|
||||||
if (!prefs)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (n=0; prefs[n].type; n++)
|
|
||||||
;
|
|
||||||
new = xmalloc ( sizeof (*new) * (n+1));
|
|
||||||
for (n=0; prefs[n].type; n++) {
|
|
||||||
new[n].type = prefs[n].type;
|
|
||||||
new[n].value = prefs[n].value;
|
|
||||||
}
|
|
||||||
new[n].type = PREFTYPE_NONE;
|
|
||||||
new[n].value = 0;
|
|
||||||
|
|
||||||
return new;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PKT_public_key *
|
|
||||||
copy_public_key ( PKT_public_key *d, PKT_public_key *s)
|
|
||||||
{
|
|
||||||
int n, i;
|
|
||||||
|
|
||||||
if( !d )
|
|
||||||
d = xmalloc (sizeof *d);
|
|
||||||
memcpy( d, s, sizeof *d );
|
|
||||||
d->user_id = scopy_user_id (s->user_id);
|
|
||||||
d->prefs = copy_prefs (s->prefs);
|
|
||||||
n = pubkey_get_npkey( s->pubkey_algo );
|
|
||||||
if( !n )
|
|
||||||
d->pkey[0] = mpi_copy(s->pkey[0]);
|
|
||||||
else {
|
|
||||||
for(i=0; i < n; i++ )
|
|
||||||
d->pkey[i] = mpi_copy( s->pkey[i] );
|
|
||||||
}
|
|
||||||
if( !s->revkey && s->numrevkeys )
|
|
||||||
BUG();
|
|
||||||
if( s->numrevkeys ) {
|
|
||||||
d->revkey = xmalloc (sizeof(struct revocation_key)*s->numrevkeys);
|
|
||||||
memcpy(d->revkey,s->revkey,sizeof(struct revocation_key)*s->numrevkeys);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
d->revkey = NULL;
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Replace all common parts of a sk by the one from the public key.
|
|
||||||
* This is a hack and a better solution will be to just store the real secret
|
|
||||||
* parts somewhere and don't duplicate all the other stuff.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
copy_public_parts_to_secret_key( PKT_public_key *pk, PKT_secret_key *sk )
|
|
||||||
{
|
|
||||||
sk->expiredate = pk->expiredate;
|
|
||||||
sk->pubkey_algo = pk->pubkey_algo;
|
|
||||||
sk->pubkey_usage= pk->pubkey_usage;
|
|
||||||
sk->req_usage = pk->req_usage;
|
|
||||||
sk->req_algo = pk->req_algo;
|
|
||||||
sk->has_expired = pk->has_expired;
|
|
||||||
sk->is_revoked = pk->is_revoked;
|
|
||||||
sk->is_valid = pk->is_valid;
|
|
||||||
sk->main_keyid[0]= pk->main_keyid[0];
|
|
||||||
sk->main_keyid[1]= pk->main_keyid[1];
|
|
||||||
sk->keyid[0] = pk->keyid[0];
|
|
||||||
sk->keyid[1] = pk->keyid[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
PKT_signature *
|
|
||||||
copy_signature( PKT_signature *d, PKT_signature *s )
|
|
||||||
{
|
|
||||||
int n, i;
|
|
||||||
|
|
||||||
if( !d )
|
|
||||||
d = xmalloc (sizeof *d);
|
|
||||||
memcpy( d, s, sizeof *d );
|
|
||||||
n = pubkey_get_nsig( s->pubkey_algo );
|
|
||||||
if( !n )
|
|
||||||
d->data[0] = mpi_copy(s->data[0]);
|
|
||||||
else {
|
|
||||||
for(i=0; i < n; i++ )
|
|
||||||
d->data[i] = mpi_copy( s->data[i] );
|
|
||||||
}
|
|
||||||
d->hashed = cp_subpktarea (s->hashed);
|
|
||||||
d->unhashed = cp_subpktarea (s->unhashed);
|
|
||||||
if(s->numrevkeys)
|
|
||||||
{
|
|
||||||
d->revkey=NULL;
|
|
||||||
d->numrevkeys=0;
|
|
||||||
parse_revkeys(d);
|
|
||||||
}
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* shallow copy of the user ID
|
|
||||||
*/
|
|
||||||
PKT_user_id *
|
|
||||||
scopy_user_id (PKT_user_id *s)
|
|
||||||
{
|
|
||||||
if (s)
|
|
||||||
s->ref++;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
release_secret_key_parts( PKT_secret_key *sk )
|
|
||||||
{
|
|
||||||
int n, i;
|
|
||||||
|
|
||||||
n = pubkey_get_nskey( sk->pubkey_algo );
|
|
||||||
if( !n )
|
|
||||||
mpi_release (sk->skey[0]);
|
|
||||||
for(i=0; i < n; i++ ) {
|
|
||||||
mpi_release ( sk->skey[i] );
|
|
||||||
sk->skey[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
free_secret_key( PKT_secret_key *sk )
|
|
||||||
{
|
|
||||||
release_secret_key_parts( sk );
|
|
||||||
xfree (sk);
|
|
||||||
}
|
|
||||||
|
|
||||||
PKT_secret_key *
|
|
||||||
copy_secret_key( PKT_secret_key *d, PKT_secret_key *s )
|
|
||||||
{
|
|
||||||
int n, i;
|
|
||||||
|
|
||||||
if( !d )
|
|
||||||
d = xmalloc (sizeof *d);
|
|
||||||
memcpy( d, s, sizeof *d );
|
|
||||||
n = pubkey_get_nskey( s->pubkey_algo );
|
|
||||||
if( !n )
|
|
||||||
d->skey[0] = mpi_copy(s->skey[0]);
|
|
||||||
else {
|
|
||||||
for(i=0; i < n; i++ )
|
|
||||||
d->skey[i] = mpi_copy( s->skey[i] );
|
|
||||||
}
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
free_comment( PKT_comment *rem )
|
|
||||||
{
|
|
||||||
xfree (rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
free_attributes(PKT_user_id *uid)
|
|
||||||
{
|
|
||||||
xfree (uid->attribs);
|
|
||||||
xfree (uid->attrib_data);
|
|
||||||
|
|
||||||
uid->attribs=NULL;
|
|
||||||
uid->attrib_data=NULL;
|
|
||||||
uid->attrib_len=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
free_user_id (PKT_user_id *uid)
|
|
||||||
{
|
|
||||||
assert (uid->ref > 0);
|
|
||||||
if (--uid->ref)
|
|
||||||
return;
|
|
||||||
|
|
||||||
free_attributes(uid);
|
|
||||||
xfree (uid->prefs);
|
|
||||||
xfree (uid->namehash);
|
|
||||||
xfree (uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
free_compressed( PKT_compressed *zd )
|
|
||||||
{
|
|
||||||
if( zd->buf ) { /* have to skip some bytes */
|
|
||||||
/* don't have any information about the length, so
|
|
||||||
* we assume this is the last packet */
|
|
||||||
while( iobuf_read( zd->buf, NULL, 1<<30 ) != -1 )
|
|
||||||
;
|
|
||||||
}
|
|
||||||
xfree (zd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
free_encrypted( PKT_encrypted *ed )
|
|
||||||
{
|
|
||||||
if( ed->buf ) { /* have to skip some bytes */
|
|
||||||
if( iobuf_in_block_mode(ed->buf) ) {
|
|
||||||
while( iobuf_read( ed->buf, NULL, 1<<30 ) != -1 )
|
|
||||||
;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
while( ed->len ) { /* skip the packet */
|
|
||||||
int n = iobuf_read( ed->buf, NULL, ed->len );
|
|
||||||
if( n == -1 )
|
|
||||||
ed->len = 0;
|
|
||||||
else
|
|
||||||
ed->len -= n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xfree (ed);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
free_plaintext( PKT_plaintext *pt )
|
|
||||||
{
|
|
||||||
if( pt->buf ) { /* have to skip some bytes */
|
|
||||||
if( iobuf_in_block_mode(pt->buf) ) {
|
|
||||||
while( iobuf_read( pt->buf, NULL, 1<<30 ) != -1 )
|
|
||||||
;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
while( pt->len ) { /* skip the packet */
|
|
||||||
int n = iobuf_read( pt->buf, NULL, pt->len );
|
|
||||||
if( n == -1 )
|
|
||||||
pt->len = 0;
|
|
||||||
else
|
|
||||||
pt->len -= n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xfree (pt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Free the packet in pkt.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
free_packet( PACKET *pkt )
|
|
||||||
{
|
|
||||||
if( !pkt || !pkt->pkt.generic )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( DBG_MEMORY )
|
|
||||||
log_debug("free_packet() type=%d\n", pkt->pkttype );
|
|
||||||
|
|
||||||
switch( pkt->pkttype ) {
|
|
||||||
case PKT_SIGNATURE:
|
|
||||||
free_seckey_enc( pkt->pkt.signature );
|
|
||||||
break;
|
|
||||||
case PKT_PUBKEY_ENC:
|
|
||||||
free_pubkey_enc( pkt->pkt.pubkey_enc );
|
|
||||||
break;
|
|
||||||
case PKT_SYMKEY_ENC:
|
|
||||||
free_symkey_enc( pkt->pkt.symkey_enc );
|
|
||||||
break;
|
|
||||||
case PKT_PUBLIC_KEY:
|
|
||||||
case PKT_PUBLIC_SUBKEY:
|
|
||||||
free_public_key( pkt->pkt.public_key );
|
|
||||||
break;
|
|
||||||
case PKT_SECRET_KEY:
|
|
||||||
case PKT_SECRET_SUBKEY:
|
|
||||||
free_secret_key( pkt->pkt.secret_key );
|
|
||||||
break;
|
|
||||||
case PKT_COMMENT:
|
|
||||||
free_comment( pkt->pkt.comment );
|
|
||||||
break;
|
|
||||||
case PKT_USER_ID:
|
|
||||||
free_user_id( pkt->pkt.user_id );
|
|
||||||
break;
|
|
||||||
case PKT_COMPRESSED:
|
|
||||||
free_compressed( pkt->pkt.compressed);
|
|
||||||
break;
|
|
||||||
case PKT_ENCRYPTED:
|
|
||||||
case PKT_ENCRYPTED_MDC:
|
|
||||||
free_encrypted( pkt->pkt.encrypted );
|
|
||||||
break;
|
|
||||||
case PKT_PLAINTEXT:
|
|
||||||
free_plaintext( pkt->pkt.plaintext );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
xfree ( pkt->pkt.generic );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pkt->pkt.generic = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* returns 0 if they match.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
cmp_public_keys( PKT_public_key *a, PKT_public_key *b )
|
|
||||||
{
|
|
||||||
int n, i;
|
|
||||||
|
|
||||||
if( a->timestamp != b->timestamp )
|
|
||||||
return -1;
|
|
||||||
if( a->version < 4 && a->expiredate != b->expiredate )
|
|
||||||
return -1;
|
|
||||||
if( a->pubkey_algo != b->pubkey_algo )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
n = pubkey_get_npkey( b->pubkey_algo );
|
|
||||||
if( !n )
|
|
||||||
return -1; /* can't compare due to unknown algorithm */
|
|
||||||
for(i=0; i < n; i++ ) {
|
|
||||||
if( mpi_cmp( a->pkey[i], b->pkey[i] ) )
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Returns 0 if they match.
|
|
||||||
* We only compare the public parts.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
cmp_secret_keys( PKT_secret_key *a, PKT_secret_key *b )
|
|
||||||
{
|
|
||||||
int n, i;
|
|
||||||
|
|
||||||
if( a->timestamp != b->timestamp )
|
|
||||||
return -1;
|
|
||||||
if( a->version < 4 && a->expiredate != b->expiredate )
|
|
||||||
return -1;
|
|
||||||
if( a->pubkey_algo != b->pubkey_algo )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
n = pubkey_get_npkey( b->pubkey_algo );
|
|
||||||
if( !n )
|
|
||||||
return -1; /* can't compare due to unknown algorithm */
|
|
||||||
for(i=0; i < n; i++ ) {
|
|
||||||
if( mpi_cmp( a->skey[i], b->skey[i] ) )
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Returns 0 if they match.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
cmp_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk )
|
|
||||||
{
|
|
||||||
int n, i;
|
|
||||||
|
|
||||||
if( pk->timestamp != sk->timestamp )
|
|
||||||
return -1;
|
|
||||||
if( pk->version < 4 && pk->expiredate != sk->expiredate )
|
|
||||||
return -1;
|
|
||||||
if( pk->pubkey_algo != sk->pubkey_algo )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
n = pubkey_get_npkey( pk->pubkey_algo );
|
|
||||||
if( !n )
|
|
||||||
return -1; /* can't compare due to unknown algorithm */
|
|
||||||
for(i=0; i < n; i++ ) {
|
|
||||||
if( mpi_cmp( pk->pkey[i] , sk->skey[i] ) )
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
cmp_signatures( PKT_signature *a, PKT_signature *b )
|
|
||||||
{
|
|
||||||
int n, i;
|
|
||||||
|
|
||||||
if( a->keyid[0] != b->keyid[0] )
|
|
||||||
return -1;
|
|
||||||
if( a->keyid[1] != b->keyid[1] )
|
|
||||||
return -1;
|
|
||||||
if( a->pubkey_algo != b->pubkey_algo )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
n = pubkey_get_nsig( a->pubkey_algo );
|
|
||||||
if( !n )
|
|
||||||
return -1; /* can't compare due to unknown algorithm */
|
|
||||||
for(i=0; i < n; i++ ) {
|
|
||||||
if( mpi_cmp( a->data[i] , b->data[i] ) )
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Returns: true if the user ids do not match
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
cmp_user_ids( PKT_user_id *a, PKT_user_id *b )
|
|
||||||
{
|
|
||||||
int res=1;
|
|
||||||
|
|
||||||
if( a == b )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if( a->attrib_data && b->attrib_data )
|
|
||||||
{
|
|
||||||
res = a->attrib_len - b->attrib_len;
|
|
||||||
if( !res )
|
|
||||||
res = memcmp( a->attrib_data, b->attrib_data, a->attrib_len );
|
|
||||||
}
|
|
||||||
else if( !a->attrib_data && !b->attrib_data )
|
|
||||||
{
|
|
||||||
res = a->len - b->len;
|
|
||||||
if( !res )
|
|
||||||
res = memcmp( a->name, b->name, a->len );
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
2618
g10/getkey.c
2618
g10/getkey.c
File diff suppressed because it is too large
Load Diff
31
g10/global.h
31
g10/global.h
@ -1,31 +0,0 @@
|
|||||||
/* global.h - Local typedefs and constants
|
|
||||||
* Copyright (C) 2001 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 GPG_GLOBAL_H
|
|
||||||
#define GPG_GLOBAL_H
|
|
||||||
|
|
||||||
#define MAX_FINGERPRINT_LEN 20
|
|
||||||
|
|
||||||
typedef struct kbnode_struct *KBNODE;
|
|
||||||
typedef struct keydb_search_desc KEYDB_SEARCH_DESC;
|
|
||||||
|
|
||||||
#include "gpg.h"
|
|
||||||
|
|
||||||
#endif /*GPG_GLOBAL_H*/
|
|
38
g10/gpg.h
38
g10/gpg.h
@ -1,38 +0,0 @@
|
|||||||
/* gpg.h - top level include file for gpg etc.
|
|
||||||
* Copyright (C) 2003 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 GNUPG_G10_GPG_H
|
|
||||||
#define GNUPG_G10_GPG_H
|
|
||||||
|
|
||||||
/* Note, that this file should be the first one after the system
|
|
||||||
header files. This is required to set the error source to the
|
|
||||||
correct value and may be of advantage if we ever have to do
|
|
||||||
special things. */
|
|
||||||
|
|
||||||
#ifdef GPG_ERR_SOURCE_DEFAULT
|
|
||||||
#error GPG_ERR_SOURCE_DEFAULT already defined
|
|
||||||
#endif
|
|
||||||
#define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GPG
|
|
||||||
#include <gpg-error.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* FIXME: merge this with global.h */
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*GNUPG_G10_GPG_H*/
|
|
389
g10/gpgv.c
389
g10/gpgv.c
@ -1,389 +0,0 @@
|
|||||||
/* gpgv.c - The GnuPG signature verify utility
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
|
|
||||||
* 2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#ifdef HAVE_DOSISH_SYSTEM
|
|
||||||
#include <fcntl.h> /* for setmode() */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define INCLUDED_BY_MAIN_MODULE 1
|
|
||||||
#include "gpg.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "iobuf.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "keydb.h"
|
|
||||||
#include "trustdb.h"
|
|
||||||
#include "mpi.h"
|
|
||||||
#include "cipher.h"
|
|
||||||
#include "filter.h"
|
|
||||||
#include "ttyio.h"
|
|
||||||
#include "i18n.h"
|
|
||||||
#include "status.h"
|
|
||||||
|
|
||||||
|
|
||||||
enum cmd_and_opt_values { aNull = 0,
|
|
||||||
oQuiet = 'q',
|
|
||||||
oVerbose = 'v',
|
|
||||||
oBatch = 500,
|
|
||||||
oKeyring,
|
|
||||||
oIgnoreTimeConflict,
|
|
||||||
oStatusFD,
|
|
||||||
oLoggerFD,
|
|
||||||
oHomedir,
|
|
||||||
aTest };
|
|
||||||
|
|
||||||
|
|
||||||
static ARGPARSE_OPTS opts[] = {
|
|
||||||
|
|
||||||
{ 301, NULL, 0, N_("@\nOptions:\n ") },
|
|
||||||
|
|
||||||
{ oVerbose, "verbose", 0, N_("verbose") },
|
|
||||||
{ oQuiet, "quiet", 0, N_("be somewhat more quiet") },
|
|
||||||
{ oKeyring, "keyring" ,2, N_("take the keys from this keyring")},
|
|
||||||
{ oIgnoreTimeConflict, "ignore-time-conflict", 0,
|
|
||||||
N_("make timestamp conflicts only a warning") },
|
|
||||||
{ oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") },
|
|
||||||
{ oLoggerFD, "logger-fd",1, "@" },
|
|
||||||
{ oHomedir, "homedir", 2, "@" }, /* defaults to "~/.gnupg" */
|
|
||||||
|
|
||||||
{0} };
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int g10_errors_seen = 0;
|
|
||||||
|
|
||||||
#ifdef __riscos__
|
|
||||||
RISCOS_GLOBAL_STATICS("GnuPG (gpgv) Heap")
|
|
||||||
#endif /* __riscos__ */
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
my_strusage( int level )
|
|
||||||
{
|
|
||||||
const char *p;
|
|
||||||
switch( level ) {
|
|
||||||
case 11: p = "gpgv (GnuPG)";
|
|
||||||
break;
|
|
||||||
case 13: p = VERSION; break;
|
|
||||||
case 17: p = PRINTABLE_OS_NAME; break;
|
|
||||||
case 19: p =
|
|
||||||
_("Please report bugs to <gnupg-bugs@gnu.org>.\n");
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
case 40: p =
|
|
||||||
_("Usage: gpgv [options] [files] (-h for help)");
|
|
||||||
break;
|
|
||||||
case 41: p =
|
|
||||||
_("Syntax: gpg [options] [files]\n"
|
|
||||||
"Check signatures against known trusted keys\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: p = NULL;
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
i18n_init(void)
|
|
||||||
{
|
|
||||||
#ifdef USE_SIMPLE_GETTEXT
|
|
||||||
set_gettext_file( PACKAGE_GT );
|
|
||||||
#else
|
|
||||||
#ifdef ENABLE_NLS
|
|
||||||
#ifdef HAVE_LC_MESSAGES
|
|
||||||
setlocale( LC_TIME, "" );
|
|
||||||
setlocale( LC_MESSAGES, "" );
|
|
||||||
#else
|
|
||||||
setlocale( LC_ALL, "" );
|
|
||||||
#endif
|
|
||||||
bindtextdomain( PACKAGE_GT, LOCALEDIR );
|
|
||||||
textdomain( PACKAGE_GT );
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
main( int argc, char **argv )
|
|
||||||
{
|
|
||||||
ARGPARSE_ARGS pargs;
|
|
||||||
int rc=0;
|
|
||||||
STRLIST sl;
|
|
||||||
STRLIST nrings=NULL;
|
|
||||||
unsigned configlineno;
|
|
||||||
|
|
||||||
#ifdef __riscos__
|
|
||||||
riscos_global_defaults();
|
|
||||||
#endif /* __riscos__ */
|
|
||||||
|
|
||||||
set_strusage (my_strusage);
|
|
||||||
log_set_prefix ("gpgv", 1);
|
|
||||||
gnupg_init_signals(0, NULL);
|
|
||||||
i18n_init();
|
|
||||||
opt.command_fd = -1; /* no command fd */
|
|
||||||
opt.pgp2_workarounds = 1;
|
|
||||||
opt.keyserver_options.auto_key_retrieve = 1;
|
|
||||||
opt.trust_model = TM_ALWAYS;
|
|
||||||
opt.batch = 1;
|
|
||||||
|
|
||||||
#if defined (_WIN32)
|
|
||||||
opt.homedir = read_w32_registry_string( NULL, "Software\\GNU\\GnuPG",
|
|
||||||
"HomeDir" );
|
|
||||||
#else
|
|
||||||
opt.homedir = getenv("GNUPGHOME");
|
|
||||||
#endif
|
|
||||||
if( !opt.homedir || !*opt.homedir ) {
|
|
||||||
opt.homedir = GNUPG_DEFAULT_HOMEDIR;
|
|
||||||
}
|
|
||||||
tty_no_terminal(1);
|
|
||||||
tty_batchmode(1);
|
|
||||||
disable_dotlock();
|
|
||||||
|
|
||||||
set_native_charset (NULL); /* Try to auto set the character set */
|
|
||||||
|
|
||||||
pargs.argc = &argc;
|
|
||||||
pargs.argv = &argv;
|
|
||||||
pargs.flags= 1; /* do not remove the args */
|
|
||||||
while( optfile_parse( NULL, NULL, &configlineno, &pargs, opts) ) {
|
|
||||||
switch( pargs.r_opt ) {
|
|
||||||
case oQuiet: opt.quiet = 1; break;
|
|
||||||
case oVerbose: g10_opt_verbose++;
|
|
||||||
opt.verbose++; opt.list_sigs=1; break;
|
|
||||||
case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break;
|
|
||||||
case oStatusFD: set_status_fd( pargs.r.ret_int ); break;
|
|
||||||
case oLoggerFD:
|
|
||||||
log_set_fd (iobuf_translate_file_handle (pargs.r.ret_int, 1));
|
|
||||||
break;
|
|
||||||
case oHomedir: opt.homedir = pargs.r.ret_str; break;
|
|
||||||
case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
|
|
||||||
default : pargs.err = 2; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( log_get_errorcount(0) )
|
|
||||||
g10_exit(2);
|
|
||||||
|
|
||||||
g10_opt_homedir = opt.homedir;
|
|
||||||
|
|
||||||
if( opt.verbose > 1 )
|
|
||||||
set_packet_list_mode(1);
|
|
||||||
|
|
||||||
if( !nrings ) /* no keyring given: use default one */
|
|
||||||
keydb_add_resource ("trustedkeys" EXTSEP_S "gpg", 0, 0);
|
|
||||||
for(sl = nrings; sl; sl = sl->next )
|
|
||||||
keydb_add_resource (sl->d, 0, 0 );
|
|
||||||
|
|
||||||
FREE_STRLIST(nrings);
|
|
||||||
|
|
||||||
if( (rc = verify_signatures( argc, argv ) ))
|
|
||||||
log_error("verify signatures failed: %s\n", gpg_strerror (rc) );
|
|
||||||
|
|
||||||
/* cleanup */
|
|
||||||
g10_exit(0);
|
|
||||||
return 8; /*NEVER REACHED*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
g10_exit( int rc )
|
|
||||||
{
|
|
||||||
rc = rc? rc : log_get_errorcount(0)? 2 :
|
|
||||||
g10_errors_seen? 1 : 0;
|
|
||||||
exit(rc );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
read_trust_options (byte *trust_model,ulong *created,ulong *nextcheck,
|
|
||||||
byte *marginals,byte *completes,byte *cert_depth)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Stub:
|
|
||||||
* We have to override the trustcheck from pkclist.c becuase
|
|
||||||
* this utility assumes that all keys in the keyring are trustworthy
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
check_signatures_trust( PKT_signature *sig )
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Stub:
|
|
||||||
* We don't have the trustdb , so we have to provide some stub functions
|
|
||||||
* instead
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
cache_disabled_value(PKT_public_key *pk)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
get_validity_info (PKT_public_key *pk, PKT_user_id *uid)
|
|
||||||
{
|
|
||||||
return '?';
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
get_validity (PKT_public_key *pk, PKT_user_id *uid)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
trust_value_to_string (unsigned int value)
|
|
||||||
{
|
|
||||||
return "err";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stub: */
|
|
||||||
int
|
|
||||||
get_ownertrust_info (PKT_public_key *pk)
|
|
||||||
{
|
|
||||||
return '?';
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
get_ownertrust (PKT_public_key *pk)
|
|
||||||
{
|
|
||||||
return TRUST_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Stub:
|
|
||||||
* Because we only work with trusted keys, it does not make sense to
|
|
||||||
* get them from a keyserver
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
keyserver_import_keyid( u32 *keyid, void *dummy )
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stub:
|
|
||||||
* No encryption here but mainproc links to these functions.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
get_session_key( PKT_pubkey_enc *k, DEK *dek )
|
|
||||||
{
|
|
||||||
return GPG_ERR_GENERAL;
|
|
||||||
}
|
|
||||||
/* Stub: */
|
|
||||||
int
|
|
||||||
get_override_session_key( DEK *dek, const char *string )
|
|
||||||
{
|
|
||||||
return GPG_ERR_GENERAL;
|
|
||||||
}
|
|
||||||
/* Stub: */
|
|
||||||
int
|
|
||||||
decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
|
|
||||||
{
|
|
||||||
return GPG_ERR_GENERAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Stub:
|
|
||||||
* No interactive commnds, so we don't need the helptexts
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
display_online_help( const char *keyword )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stub:
|
|
||||||
* We don't use secret keys, but getkey.c links to this
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
check_secret_key( PKT_secret_key *sk, int n )
|
|
||||||
{
|
|
||||||
return GPG_ERR_GENERAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stub:
|
|
||||||
* No secret key, so no passphrase needed
|
|
||||||
*/
|
|
||||||
DEK *
|
|
||||||
passphrase_to_dek( u32 *keyid, int pubkey_algo,
|
|
||||||
int cipher_algo, STRING2KEY *s2k, int mode,
|
|
||||||
const char *tmp, int *canceled)
|
|
||||||
{
|
|
||||||
if (canceled)
|
|
||||||
*canceled = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stubs to avoid linking to photoid.c */
|
|
||||||
void show_photos(const struct user_attribute *attrs,int count,PKT_public_key *pk) {}
|
|
||||||
int parse_image_header(const struct user_attribute *attr,byte *type,u32 *len) {return 0;}
|
|
||||||
char *image_type_to_string(byte type,int string) {return NULL;}
|
|
||||||
|
|
||||||
/* Stubs to void linking to ../cipher/cipher.c */
|
|
||||||
int string_to_cipher_algo( const char *string ) { return 0; }
|
|
||||||
const char *cipher_algo_to_string( int algo ) { return "?";}
|
|
||||||
void disable_cipher_algo( int algo ) {}
|
|
||||||
int check_cipher_algo( int algo ) { return -1;}
|
|
||||||
unsigned int cipher_get_keylen( int algo ) { return 0; }
|
|
||||||
unsigned int cipher_get_blocksize( int algo ) {return 0;}
|
|
||||||
CIPHER_HANDLE cipher_open( int algo, int mode, int secure ) { return NULL;}
|
|
||||||
void cipher_close( CIPHER_HANDLE c ) {}
|
|
||||||
int cipher_setkey( CIPHER_HANDLE c, byte *key, unsigned keylen ) { return -1;}
|
|
||||||
void cipher_setiv( CIPHER_HANDLE c, const byte *iv, unsigned ivlen ){}
|
|
||||||
void cipher_encrypt( CIPHER_HANDLE c, byte *outbuf,
|
|
||||||
byte *inbuf, unsigned nbytes ) {}
|
|
||||||
void cipher_decrypt( CIPHER_HANDLE c, byte *outbuf,
|
|
||||||
byte *inbuf, unsigned nbytes ) {}
|
|
||||||
void cipher_sync( CIPHER_HANDLE c ) {}
|
|
||||||
|
|
||||||
|
|
||||||
/* Stubs to avoid linking to ../util/ttyio.c */
|
|
||||||
int tty_batchmode( int onoff ) { return 0; }
|
|
||||||
void tty_printf( const char *fmt, ... ) { }
|
|
||||||
void tty_print_string( const byte *p, size_t n ) { }
|
|
||||||
void tty_print_utf8_string( const byte *p, size_t n ) {}
|
|
||||||
void tty_print_utf8_string2( const byte *p, size_t n, size_t max_n ) {}
|
|
||||||
char *tty_get( const char *prompt ) { return NULL;}
|
|
||||||
char *tty_get_hidden( const char *prompt ) {return NULL; }
|
|
||||||
void tty_kill_prompt(void) {}
|
|
||||||
int tty_get_answer_is_yes( const char *prompt ) {return 0;}
|
|
||||||
int tty_no_terminal(int onoff) {return 0;}
|
|
||||||
|
|
||||||
/* We do not do any locking, so use these stubs here */
|
|
||||||
void disable_dotlock(void) {}
|
|
||||||
DOTLOCK create_dotlock( const char *file_to_lock ) { return NULL; }
|
|
||||||
int make_dotlock( DOTLOCK h, long timeout ) { return 0;}
|
|
||||||
int release_dotlock( DOTLOCK h ) {return 0;}
|
|
||||||
void dotlock_remove_lockfiles(void) {}
|
|
316
g10/helptext.c
316
g10/helptext.c
@ -1,316 +0,0 @@
|
|||||||
/* helptext.c - English help texts
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "gpg.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "ttyio.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "i18n.h"
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* These helptexts are used for the "online" help feature. We use
|
|
||||||
* a key consisting of words and dots. Because the lookup is only
|
|
||||||
* done in an interactive mode on a user request (when she enters a "?"
|
|
||||||
* as response to a prompt) we can use a simple search through the list.
|
|
||||||
*
|
|
||||||
* Mini glossary:
|
|
||||||
*
|
|
||||||
* "user ID", "trustdb", "NOTE" and "WARNING".
|
|
||||||
*/
|
|
||||||
|
|
||||||
static struct helptexts { const char *key; const char *help; } helptexts[] = {
|
|
||||||
|
|
||||||
/* begin of list */
|
|
||||||
|
|
||||||
{ "edit_ownertrust.value", N_(
|
|
||||||
"It's up to you to assign a value here; this value will never be exported\n"
|
|
||||||
"to any 3rd party. We need it to implement the web-of-trust; it has nothing\n"
|
|
||||||
"to do with the (implicitly created) web-of-certificates."
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "edit_ownertrust.set_ultimate.okay", N_(
|
|
||||||
"To build the Web-of-Trust, GnuPG needs to know which keys are\n"
|
|
||||||
"ultimately trusted - those are usually the keys for which you have\n"
|
|
||||||
"access to the secret key. Answer \"yes\" to set this key to\n"
|
|
||||||
"ultimately trusted\n"
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "revoked_key.override", N_(
|
|
||||||
"If you want to use this revoked key anyway, answer \"yes\"."
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "untrusted_key.override", N_(
|
|
||||||
"If you want to use this untrusted key anyway, answer \"yes\"."
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "pklist.user_id.enter", N_(
|
|
||||||
"Enter the user ID of the addressee to whom you want to send the message."
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "keygen.algo", N_(
|
|
||||||
"Select the algorithm to use.\n"
|
|
||||||
"\n"
|
|
||||||
"DSA (aka DSS) is the digital signature algorithm which can only be used\n"
|
|
||||||
"for signatures. This is the suggested algorithm because verification of\n"
|
|
||||||
"DSA signatures are much faster than those of ElGamal.\n"
|
|
||||||
"\n"
|
|
||||||
"ElGamal is an algorithm which can be used for signatures and encryption.\n"
|
|
||||||
"OpenPGP distinguishs between two flavors of this algorithms: an encrypt only\n"
|
|
||||||
"and a sign+encrypt; actually it is the same, but some parameters must be\n"
|
|
||||||
"selected in a special way to create a safe key for signatures: this program\n"
|
|
||||||
"does this but other OpenPGP implementations are not required to understand\n"
|
|
||||||
"the signature+encryption flavor.\n"
|
|
||||||
"\n"
|
|
||||||
"The first (primary) key must always be a key which is capable of signing;\n"
|
|
||||||
"this is the reason why the encryption only ElGamal key is not available in\n"
|
|
||||||
"this menu."
|
|
||||||
)},
|
|
||||||
|
|
||||||
|
|
||||||
{ "keygen.algo.elg_se", N_(
|
|
||||||
"Although these keys are defined in RFC2440 they are not suggested\n"
|
|
||||||
"because they are not supported by all programs and signatures created\n"
|
|
||||||
"with them are quite large and very slow to verify."
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "keygen.algo.rsa_se", N_(
|
|
||||||
"In general it is not a good idea to use the same key for signing and\n"
|
|
||||||
"encryption. This algorithm should only be used in certain domains.\n"
|
|
||||||
"Please consult your security expert first."
|
|
||||||
)},
|
|
||||||
|
|
||||||
|
|
||||||
{ "keygen.size", N_(
|
|
||||||
"Enter the size of the key"
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "keygen.size.huge.okay", N_(
|
|
||||||
"Answer \"yes\" or \"no\""
|
|
||||||
)},
|
|
||||||
|
|
||||||
|
|
||||||
{ "keygen.size.large.okay", N_(
|
|
||||||
"Answer \"yes\" or \"no\""
|
|
||||||
)},
|
|
||||||
|
|
||||||
|
|
||||||
{ "keygen.valid", N_(
|
|
||||||
"Enter the required value as shown in the prompt.\n"
|
|
||||||
"It is possible to enter a ISO date (YYYY-MM-DD) but you won't\n"
|
|
||||||
"get a good error response - instead the system tries to interpret\n"
|
|
||||||
"the given value as an interval."
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "keygen.valid.okay", N_(
|
|
||||||
"Answer \"yes\" or \"no\""
|
|
||||||
)},
|
|
||||||
|
|
||||||
|
|
||||||
{ "keygen.name", N_(
|
|
||||||
"Enter the name of the key holder"
|
|
||||||
)},
|
|
||||||
|
|
||||||
|
|
||||||
{ "keygen.email", N_(
|
|
||||||
"please enter an optional but highly suggested email address"
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "keygen.comment", N_(
|
|
||||||
"Please enter an optional comment"
|
|
||||||
)},
|
|
||||||
|
|
||||||
|
|
||||||
{ "keygen.userid.cmd", N_(
|
|
||||||
""
|
|
||||||
"N to change the name.\n"
|
|
||||||
"C to change the comment.\n"
|
|
||||||
"E to change the email address.\n"
|
|
||||||
"O to continue with key generation.\n"
|
|
||||||
"Q to to quit the key generation."
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "keygen.sub.okay", N_(
|
|
||||||
"Answer \"yes\" (or just \"y\") if it is okay to generate the sub key."
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "sign_uid.okay", N_(
|
|
||||||
"Answer \"yes\" or \"no\""
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "sign_uid.class", N_(
|
|
||||||
"When you sign a user ID on a key, you should first verify that the key\n"
|
|
||||||
"belongs to the person named in the user ID. It is useful for others to\n"
|
|
||||||
"know how carefully you verified this.\n\n"
|
|
||||||
"\"0\" means you make no particular claim as to how carefully you verified the\n"
|
|
||||||
" key.\n\n"
|
|
||||||
"\"1\" means you believe the key is owned by the person who claims to own it\n"
|
|
||||||
" but you could not, or did not verify the key at all. This is useful for\n"
|
|
||||||
" a \"persona\" verification, where you sign the key of a pseudonymous user.\n\n"
|
|
||||||
"\"2\" means you did casual verification of the key. For example, this could\n"
|
|
||||||
" mean that you verified the key fingerprint and checked the user ID on the\n"
|
|
||||||
" key against a photo ID.\n\n"
|
|
||||||
"\"3\" means you did extensive verification of the key. For example, this could\n"
|
|
||||||
" mean that you verified the key fingerprint with the owner of the key in\n"
|
|
||||||
" person, and that you checked, by means of a hard to forge document with a\n"
|
|
||||||
" photo ID (such as a passport) that the name of the key owner matches the\n"
|
|
||||||
" name in the user ID on the key, and finally that you verified (by exchange\n"
|
|
||||||
" of email) that the email address on the key belongs to the key owner.\n\n"
|
|
||||||
"Note that the examples given above for levels 2 and 3 are *only* examples.\n"
|
|
||||||
"In the end, it is up to you to decide just what \"casual\" and \"extensive\"\n"
|
|
||||||
"mean to you when you sign other keys.\n\n"
|
|
||||||
"If you don't know what the right answer is, answer \"0\"."
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "change_passwd.empty.okay", N_(
|
|
||||||
"Answer \"yes\" or \"no\""
|
|
||||||
)},
|
|
||||||
|
|
||||||
|
|
||||||
{ "keyedit.save.okay", N_(
|
|
||||||
"Answer \"yes\" or \"no\""
|
|
||||||
)},
|
|
||||||
|
|
||||||
|
|
||||||
{ "keyedit.cancel.okay", N_(
|
|
||||||
"Answer \"yes\" or \"no\""
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "keyedit.sign_all.okay", N_(
|
|
||||||
"Answer \"yes\" is you want to sign ALL the user IDs"
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "keyedit.remove.uid.okay", N_(
|
|
||||||
"Answer \"yes\" if you really want to delete this user ID.\n"
|
|
||||||
"All certificates are then also lost!"
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "keyedit.remove.subkey.okay", N_(
|
|
||||||
"Answer \"yes\" if it is okay to delete the subkey"
|
|
||||||
)},
|
|
||||||
|
|
||||||
|
|
||||||
{ "keyedit.delsig.valid", N_(
|
|
||||||
"This is a valid signature on the key; you normally don't want\n"
|
|
||||||
"to delete this signature because it may be important to establish a\n"
|
|
||||||
"trust connection to the key or another key certified by this key."
|
|
||||||
)},
|
|
||||||
{ "keyedit.delsig.unknown", N_(
|
|
||||||
"This signature can't be checked because you don't have the\n"
|
|
||||||
"corresponding key. You should postpone its deletion until you\n"
|
|
||||||
"know which key was used because this signing key might establish\n"
|
|
||||||
"a trust connection through another already certified key."
|
|
||||||
)},
|
|
||||||
{ "keyedit.delsig.invalid", N_(
|
|
||||||
"The signature is not valid. It does make sense to remove it from\n"
|
|
||||||
"your keyring."
|
|
||||||
)},
|
|
||||||
{ "keyedit.delsig.selfsig", N_(
|
|
||||||
"This is a signature which binds the user ID to the key. It is\n"
|
|
||||||
"usually not a good idea to remove such a signature. Actually\n"
|
|
||||||
"GnuPG might not be able to use this key anymore. So do this\n"
|
|
||||||
"only if this self-signature is for some reason not valid and\n"
|
|
||||||
"a second one is available."
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "keyedit.updpref.okay", N_(
|
|
||||||
"Change the preferences of all user IDs (or just of the selected ones)\n"
|
|
||||||
"to the current list of preferences. The timestamp of all affected\n"
|
|
||||||
"self-signatures will be advanced by one second.\n"
|
|
||||||
)},
|
|
||||||
|
|
||||||
|
|
||||||
{ "passphrase.enter", N_(
|
|
||||||
""
|
|
||||||
"Please enter the passhrase; this is a secret sentence \n"
|
|
||||||
)},
|
|
||||||
|
|
||||||
|
|
||||||
{ "passphrase.repeat", N_(
|
|
||||||
"Please repeat the last passphrase, so you are sure what you typed in."
|
|
||||||
)},
|
|
||||||
|
|
||||||
{ "detached_signature.filename", N_(
|
|
||||||
"Give the name of the file to which the signature applies"
|
|
||||||
)},
|
|
||||||
|
|
||||||
/* openfile.c (overwrite_filep) */
|
|
||||||
{ "openfile.overwrite.okay", N_(
|
|
||||||
"Answer \"yes\" if it is okay to overwrite the file"
|
|
||||||
)},
|
|
||||||
|
|
||||||
/* openfile.c (ask_outfile_name) */
|
|
||||||
{ "openfile.askoutname", N_(
|
|
||||||
"Please enter a new filename. If you just hit RETURN the default\n"
|
|
||||||
"file (which is shown in brackets) will be used."
|
|
||||||
)},
|
|
||||||
|
|
||||||
/* revoke.c (ask_revocation_reason) */
|
|
||||||
{ "ask_revocation_reason.code", N_(
|
|
||||||
"You should specify a reason for the certification. Depending on the\n"
|
|
||||||
"context you have the ability to choose from this list:\n"
|
|
||||||
" \"Key has been compromised\"\n"
|
|
||||||
" Use this if you have a reason to believe that unauthorized persons\n"
|
|
||||||
" got access to your secret key.\n"
|
|
||||||
" \"Key is superseded\"\n"
|
|
||||||
" Use this if you have replaced this key with a newer one.\n"
|
|
||||||
" \"Key is no longer used\"\n"
|
|
||||||
" Use this if you have retired this key.\n"
|
|
||||||
" \"User ID is no longer valid\"\n"
|
|
||||||
" Use this to state that the user ID should not longer be used;\n"
|
|
||||||
" this is normally used to mark an email address invalid.\n"
|
|
||||||
)},
|
|
||||||
|
|
||||||
/* revoke.c (ask_revocation_reason) */
|
|
||||||
{ "ask_revocation_reason.text", N_(
|
|
||||||
"If you like, you can enter a text describing why you issue this\n"
|
|
||||||
"revocation certificate. Please keep this text concise.\n"
|
|
||||||
"An empty line ends the text.\n"
|
|
||||||
)},
|
|
||||||
|
|
||||||
/* end of list */
|
|
||||||
{ NULL, NULL } };
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
display_online_help( const char *keyword )
|
|
||||||
{
|
|
||||||
|
|
||||||
tty_kill_prompt();
|
|
||||||
if( !keyword )
|
|
||||||
tty_printf(_("No help available") );
|
|
||||||
else {
|
|
||||||
const char *p;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i=0; (p=helptexts[i].key) && strcmp( p, keyword ); i++ )
|
|
||||||
;
|
|
||||||
if( !p || !*helptexts[i].help )
|
|
||||||
tty_printf(_("No help available for `%s'"), keyword );
|
|
||||||
else
|
|
||||||
tty_printf("%s", _(helptexts[i].help) );
|
|
||||||
}
|
|
||||||
tty_printf("\n");
|
|
||||||
}
|
|
1906
g10/import.c
1906
g10/import.c
File diff suppressed because it is too large
Load Diff
401
g10/kbnode.c
401
g10/kbnode.c
@ -1,401 +0,0 @@
|
|||||||
/* kbnode.c - keyblock node utility functions
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "gpg.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "keydb.h"
|
|
||||||
|
|
||||||
#define USE_UNUSED_NODES 1
|
|
||||||
|
|
||||||
static KBNODE unused_nodes;
|
|
||||||
|
|
||||||
static KBNODE
|
|
||||||
alloc_node(void)
|
|
||||||
{
|
|
||||||
KBNODE n;
|
|
||||||
|
|
||||||
n = unused_nodes;
|
|
||||||
if( n )
|
|
||||||
unused_nodes = n->next;
|
|
||||||
else
|
|
||||||
n = xmalloc ( sizeof *n );
|
|
||||||
n->next = NULL;
|
|
||||||
n->pkt = NULL;
|
|
||||||
n->flag = 0;
|
|
||||||
n->private_flag=0;
|
|
||||||
n->recno = 0;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
free_node( KBNODE n )
|
|
||||||
{
|
|
||||||
if( n ) {
|
|
||||||
#if USE_UNUSED_NODES
|
|
||||||
n->next = unused_nodes;
|
|
||||||
unused_nodes = n;
|
|
||||||
#else
|
|
||||||
xfree ( n );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
KBNODE
|
|
||||||
new_kbnode( PACKET *pkt )
|
|
||||||
{
|
|
||||||
KBNODE n = alloc_node();
|
|
||||||
n->pkt = pkt;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
KBNODE
|
|
||||||
clone_kbnode( KBNODE node )
|
|
||||||
{
|
|
||||||
KBNODE n = alloc_node();
|
|
||||||
|
|
||||||
n->pkt = node->pkt;
|
|
||||||
n->private_flag = node->private_flag | 2; /* mark cloned */
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
release_kbnode( KBNODE n )
|
|
||||||
{
|
|
||||||
KBNODE n2;
|
|
||||||
|
|
||||||
while( n ) {
|
|
||||||
n2 = n->next;
|
|
||||||
if( !is_cloned_kbnode(n) ) {
|
|
||||||
free_packet( n->pkt );
|
|
||||||
xfree ( n->pkt );
|
|
||||||
}
|
|
||||||
free_node( n );
|
|
||||||
n = n2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Delete NODE.
|
|
||||||
* Note: This only works with walk_kbnode!!
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
delete_kbnode( KBNODE node )
|
|
||||||
{
|
|
||||||
node->private_flag |= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Append NODE to ROOT. ROOT must exist!
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
add_kbnode( KBNODE root, KBNODE node )
|
|
||||||
{
|
|
||||||
KBNODE n1;
|
|
||||||
|
|
||||||
for(n1=root; n1->next; n1 = n1->next)
|
|
||||||
;
|
|
||||||
n1->next = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Insert NODE into the list after root but before a packet which is not of
|
|
||||||
* type PKTTYPE
|
|
||||||
* (only if PKTTYPE != 0)
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
insert_kbnode( KBNODE root, KBNODE node, int pkttype )
|
|
||||||
{
|
|
||||||
if( !pkttype ) {
|
|
||||||
node->next = root->next;
|
|
||||||
root->next = node;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
KBNODE n1;
|
|
||||||
|
|
||||||
for(n1=root; n1->next; n1 = n1->next)
|
|
||||||
if( pkttype != n1->next->pkt->pkttype ) {
|
|
||||||
node->next = n1->next;
|
|
||||||
n1->next = node;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* no such packet, append */
|
|
||||||
node->next = NULL;
|
|
||||||
n1->next = node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Find the previous node (if PKTTYPE = 0) or the previous node
|
|
||||||
* with pkttype PKTTYPE in the list starting with ROOT of NODE.
|
|
||||||
*/
|
|
||||||
KBNODE
|
|
||||||
find_prev_kbnode( KBNODE root, KBNODE node, int pkttype )
|
|
||||||
{
|
|
||||||
KBNODE n1;
|
|
||||||
|
|
||||||
for (n1=NULL; root && root != node; root = root->next ) {
|
|
||||||
if (!pkttype ||root->pkt->pkttype == pkttype)
|
|
||||||
n1 = root;
|
|
||||||
}
|
|
||||||
return n1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Ditto, but find the next packet. The behaviour is trivial if
|
|
||||||
* PKTTYPE is 0 but if it is specified, the next node with a packet
|
|
||||||
* of this type is returned. The function has some knowledge about
|
|
||||||
* the valid ordering of packets: e.g. if the next signature packet
|
|
||||||
* is requested, the function will not return one if it encounters
|
|
||||||
* a user-id.
|
|
||||||
*/
|
|
||||||
KBNODE
|
|
||||||
find_next_kbnode( KBNODE node, int pkttype )
|
|
||||||
{
|
|
||||||
for( node=node->next ; node; node = node->next ) {
|
|
||||||
if( !pkttype )
|
|
||||||
return node;
|
|
||||||
else if( pkttype == PKT_USER_ID
|
|
||||||
&& ( node->pkt->pkttype == PKT_PUBLIC_KEY
|
|
||||||
|| node->pkt->pkttype == PKT_SECRET_KEY ) )
|
|
||||||
return NULL;
|
|
||||||
else if( pkttype == PKT_SIGNATURE
|
|
||||||
&& ( node->pkt->pkttype == PKT_USER_ID
|
|
||||||
|| node->pkt->pkttype == PKT_PUBLIC_KEY
|
|
||||||
|| node->pkt->pkttype == PKT_SECRET_KEY ) )
|
|
||||||
return NULL;
|
|
||||||
else if( node->pkt->pkttype == pkttype )
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
KBNODE
|
|
||||||
find_kbnode( KBNODE node, int pkttype )
|
|
||||||
{
|
|
||||||
for( ; node; node = node->next ) {
|
|
||||||
if( node->pkt->pkttype == pkttype )
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Walk through a list of kbnodes. This function returns
|
|
||||||
* the next kbnode for each call; before using the function the first
|
|
||||||
* time, the caller must set CONTEXT to NULL (This has simply the effect
|
|
||||||
* to start with ROOT).
|
|
||||||
*/
|
|
||||||
KBNODE
|
|
||||||
walk_kbnode( KBNODE root, KBNODE *context, int all )
|
|
||||||
{
|
|
||||||
KBNODE n;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if( !*context ) {
|
|
||||||
*context = root;
|
|
||||||
n = root;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
n = (*context)->next;
|
|
||||||
*context = n;
|
|
||||||
}
|
|
||||||
} while( !all && n && is_deleted_kbnode(n) );
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
clear_kbnode_flags( KBNODE n )
|
|
||||||
{
|
|
||||||
for( ; n; n = n->next ) {
|
|
||||||
n->flag = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Commit changes made to the kblist at ROOT. Note that ROOT my change,
|
|
||||||
* and it is therefore passed by reference.
|
|
||||||
* The function has the effect of removing all nodes marked as deleted.
|
|
||||||
* returns true if any node has been changed
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
commit_kbnode( KBNODE *root )
|
|
||||||
{
|
|
||||||
KBNODE n, nl;
|
|
||||||
int changed = 0;
|
|
||||||
|
|
||||||
for( n = *root, nl=NULL; n; n = nl->next ) {
|
|
||||||
if( is_deleted_kbnode(n) ) {
|
|
||||||
if( n == *root )
|
|
||||||
*root = nl = n->next;
|
|
||||||
else
|
|
||||||
nl->next = n->next;
|
|
||||||
if( !is_cloned_kbnode(n) ) {
|
|
||||||
free_packet( n->pkt );
|
|
||||||
xfree ( n->pkt );
|
|
||||||
}
|
|
||||||
free_node( n );
|
|
||||||
changed = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
nl = n;
|
|
||||||
}
|
|
||||||
return changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
remove_kbnode( KBNODE *root, KBNODE node )
|
|
||||||
{
|
|
||||||
KBNODE n, nl;
|
|
||||||
|
|
||||||
for( n = *root, nl=NULL; n; n = nl->next ) {
|
|
||||||
if( n == node ) {
|
|
||||||
if( n == *root )
|
|
||||||
*root = nl = n->next;
|
|
||||||
else
|
|
||||||
nl->next = n->next;
|
|
||||||
if( !is_cloned_kbnode(n) ) {
|
|
||||||
free_packet( n->pkt );
|
|
||||||
xfree ( n->pkt );
|
|
||||||
}
|
|
||||||
free_node( n );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
nl = n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Move NODE behind right after WHERE or to the beginning if WHERE is NULL.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
move_kbnode( KBNODE *root, KBNODE node, KBNODE where )
|
|
||||||
{
|
|
||||||
KBNODE tmp, prev;
|
|
||||||
|
|
||||||
if( !root || !*root || !node )
|
|
||||||
return; /* sanity check */
|
|
||||||
for( prev = *root; prev && prev->next != node; prev = prev->next )
|
|
||||||
;
|
|
||||||
if( !prev )
|
|
||||||
return; /* node is not in the list */
|
|
||||||
|
|
||||||
if( !where ) { /* move node before root */
|
|
||||||
if( node == *root ) /* move to itself */
|
|
||||||
return;
|
|
||||||
prev->next = node->next;
|
|
||||||
node->next = *root;
|
|
||||||
*root = node;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* move it after where */
|
|
||||||
if( node == where )
|
|
||||||
return;
|
|
||||||
tmp = node->next;
|
|
||||||
node->next = where->next;
|
|
||||||
where->next = node;
|
|
||||||
prev->next = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
dump_kbnode( KBNODE node )
|
|
||||||
{
|
|
||||||
for(; node; node = node->next ) {
|
|
||||||
const char *s;
|
|
||||||
switch( node->pkt->pkttype ) {
|
|
||||||
case 0: s="empty"; break;
|
|
||||||
case PKT_PUBLIC_KEY: s="public-key"; break;
|
|
||||||
case PKT_SECRET_KEY: s="secret-key"; break;
|
|
||||||
case PKT_SECRET_SUBKEY: s= "secret-subkey"; break;
|
|
||||||
case PKT_PUBKEY_ENC: s="public-enc"; break;
|
|
||||||
case PKT_SIGNATURE: s="signature"; break;
|
|
||||||
case PKT_ONEPASS_SIG: s="onepass-sig"; break;
|
|
||||||
case PKT_USER_ID: s="user-id"; break;
|
|
||||||
case PKT_PUBLIC_SUBKEY: s="public-subkey"; break;
|
|
||||||
case PKT_COMMENT: s="comment"; break;
|
|
||||||
case PKT_RING_TRUST: s="trust"; break;
|
|
||||||
case PKT_PLAINTEXT: s="plaintext"; break;
|
|
||||||
case PKT_COMPRESSED: s="compressed"; break;
|
|
||||||
case PKT_ENCRYPTED: s="encrypted"; break;
|
|
||||||
case PKT_GPG_CONTROL: s="gpg-control"; break;
|
|
||||||
default: s="unknown"; break;
|
|
||||||
}
|
|
||||||
fprintf(stderr, "node %p %02x/%02x type=%s",
|
|
||||||
node, node->flag, node->private_flag, s);
|
|
||||||
if( node->pkt->pkttype == PKT_USER_ID ) {
|
|
||||||
PKT_user_id *uid = node->pkt->pkt.user_id;
|
|
||||||
fputs(" \"", stderr);
|
|
||||||
print_string( stderr, uid->name, uid->len, 0 );
|
|
||||||
fprintf (stderr, "\" %c%c%c%c\n",
|
|
||||||
uid->is_expired? 'e':'.',
|
|
||||||
uid->is_revoked? 'r':'.',
|
|
||||||
uid->created? 'v':'.',
|
|
||||||
uid->is_primary? 'p':'.' );
|
|
||||||
}
|
|
||||||
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
|
|
||||||
fprintf(stderr, " class=%02x keyid=%08lX ts=%lu\n",
|
|
||||||
node->pkt->pkt.signature->sig_class,
|
|
||||||
(ulong)node->pkt->pkt.signature->keyid[1],
|
|
||||||
(ulong)node->pkt->pkt.signature->timestamp);
|
|
||||||
}
|
|
||||||
else if( node->pkt->pkttype == PKT_GPG_CONTROL ) {
|
|
||||||
fprintf(stderr, " ctrl=%d len=%u\n",
|
|
||||||
node->pkt->pkt.gpg_control->control,
|
|
||||||
(unsigned int)node->pkt->pkt.gpg_control->datalen);
|
|
||||||
}
|
|
||||||
else if( node->pkt->pkttype == PKT_PUBLIC_KEY
|
|
||||||
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
|
|
||||||
PKT_public_key *pk = node->pkt->pkt.public_key;
|
|
||||||
fprintf(stderr, " keyid=%08lX a=%d u=%d %c%c%c%c\n",
|
|
||||||
(ulong)keyid_from_pk( pk, NULL ),
|
|
||||||
pk->pubkey_algo, pk->pubkey_usage,
|
|
||||||
pk->has_expired? 'e':'.',
|
|
||||||
pk->is_revoked? 'r':'.',
|
|
||||||
pk->is_valid? 'v':'.',
|
|
||||||
pk->mdc_feature? 'm':'.');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fputs("\n", stderr);
|
|
||||||
}
|
|
||||||
}
|
|
725
g10/keydb.c
725
g10/keydb.c
@ -1,725 +0,0 @@
|
|||||||
/* keydb.c - key database dispatcher
|
|
||||||
* Copyright (C) 2001, 2002, 2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "gpg.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "main.h" /*try_make_homedir ()*/
|
|
||||||
#include "packet.h"
|
|
||||||
#include "keyring.h"
|
|
||||||
#include "keydb.h"
|
|
||||||
#include "i18n.h"
|
|
||||||
|
|
||||||
static int active_handles;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
KEYDB_RESOURCE_TYPE_NONE = 0,
|
|
||||||
KEYDB_RESOURCE_TYPE_KEYRING
|
|
||||||
} KeydbResourceType;
|
|
||||||
#define MAX_KEYDB_RESOURCES 40
|
|
||||||
|
|
||||||
struct resource_item {
|
|
||||||
KeydbResourceType type;
|
|
||||||
union {
|
|
||||||
KEYRING_HANDLE kr;
|
|
||||||
} u;
|
|
||||||
void *token;
|
|
||||||
int secret;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
|
|
||||||
static int used_resources;
|
|
||||||
static void *primary_keyring=NULL;
|
|
||||||
|
|
||||||
struct keydb_handle {
|
|
||||||
int locked;
|
|
||||||
int found;
|
|
||||||
int current;
|
|
||||||
int used; /* items in active */
|
|
||||||
struct resource_item active[MAX_KEYDB_RESOURCES];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static int lock_all (KEYDB_HANDLE hd);
|
|
||||||
static void unlock_all (KEYDB_HANDLE hd);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Register a resource (which currently may only be a keyring file).
|
|
||||||
* The first keyring which is added by this function is
|
|
||||||
* created if it does not exist.
|
|
||||||
* Note: this function may be called before secure memory is
|
|
||||||
* available.
|
|
||||||
* Flag 1 == force
|
|
||||||
* Flag 2 == default
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
keydb_add_resource (const char *url, int flags, int secret)
|
|
||||||
{
|
|
||||||
static int any_secret, any_public;
|
|
||||||
const char *resname = url;
|
|
||||||
iobuf_t iobuf = NULL;
|
|
||||||
char *filename = NULL;
|
|
||||||
int force=(flags&1);
|
|
||||||
int rc = 0;
|
|
||||||
KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
|
|
||||||
void *token;
|
|
||||||
|
|
||||||
/* Do we have an URL?
|
|
||||||
* gnupg-ring:filename := this is a plain keyring
|
|
||||||
* filename := See what is is, but create as plain keyring.
|
|
||||||
*/
|
|
||||||
if (strlen (resname) > 11) {
|
|
||||||
if (!strncmp( resname, "gnupg-ring:", 11) ) {
|
|
||||||
rt = KEYDB_RESOURCE_TYPE_KEYRING;
|
|
||||||
resname += 11;
|
|
||||||
}
|
|
||||||
#if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
|
|
||||||
else if (strchr (resname, ':')) {
|
|
||||||
log_error ("invalid key resource URL `%s'\n", url );
|
|
||||||
rc = GPG_ERR_GENERAL;
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
#endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*resname != DIRSEP_C ) { /* do tilde expansion etc */
|
|
||||||
if (strchr(resname, DIRSEP_C) )
|
|
||||||
filename = make_filename (resname, NULL);
|
|
||||||
else
|
|
||||||
filename = make_filename (opt.homedir, resname, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
filename = xstrdup (resname);
|
|
||||||
|
|
||||||
if (!force)
|
|
||||||
force = secret? !any_secret : !any_public;
|
|
||||||
|
|
||||||
/* see whether we can determine the filetype */
|
|
||||||
if (rt == KEYDB_RESOURCE_TYPE_NONE) {
|
|
||||||
FILE *fp = fopen( filename, "rb" );
|
|
||||||
|
|
||||||
if (fp) {
|
|
||||||
u32 magic;
|
|
||||||
|
|
||||||
if (fread( &magic, 4, 1, fp) == 1 ) {
|
|
||||||
if (magic == 0x13579ace || magic == 0xce9a5713)
|
|
||||||
; /* GDBM magic - no more support */
|
|
||||||
else
|
|
||||||
rt = KEYDB_RESOURCE_TYPE_KEYRING;
|
|
||||||
}
|
|
||||||
else /* maybe empty: assume ring */
|
|
||||||
rt = KEYDB_RESOURCE_TYPE_KEYRING;
|
|
||||||
fclose( fp );
|
|
||||||
}
|
|
||||||
else /* no file yet: create ring */
|
|
||||||
rt = KEYDB_RESOURCE_TYPE_KEYRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (rt) {
|
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
|
||||||
log_error ("unknown type of key resource `%s'\n", url );
|
|
||||||
rc = GPG_ERR_GENERAL;
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
|
||||||
if (access(filename, F_OK))
|
|
||||||
{ /* file does not exist */
|
|
||||||
mode_t oldmask;
|
|
||||||
char *last_slash_in_filename;
|
|
||||||
|
|
||||||
if (!force)
|
|
||||||
{
|
|
||||||
rc = gpg_error_from_errno (errno);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
last_slash_in_filename = strrchr (filename, DIRSEP_C);
|
|
||||||
*last_slash_in_filename = 0;
|
|
||||||
if (access(filename, F_OK))
|
|
||||||
{ /* On the first time we try to create the default
|
|
||||||
homedir and check again. */
|
|
||||||
static int tried;
|
|
||||||
|
|
||||||
if (!tried)
|
|
||||||
{
|
|
||||||
tried = 1;
|
|
||||||
try_make_homedir (filename);
|
|
||||||
}
|
|
||||||
if (access (filename, F_OK))
|
|
||||||
{
|
|
||||||
rc = gpg_error_from_errno (errno);
|
|
||||||
*last_slash_in_filename = DIRSEP_C;
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*last_slash_in_filename = DIRSEP_C;
|
|
||||||
|
|
||||||
oldmask=umask(077);
|
|
||||||
iobuf = iobuf_create (filename);
|
|
||||||
umask(oldmask);
|
|
||||||
if (!iobuf)
|
|
||||||
{
|
|
||||||
log_error ( _("error creating keyring `%s': %s\n"),
|
|
||||||
filename, strerror(errno));
|
|
||||||
rc = gpg_error_from_errno (errno);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!opt.quiet)
|
|
||||||
log_info (_("keyring `%s' created\n"), filename);
|
|
||||||
iobuf_close (iobuf);
|
|
||||||
iobuf = NULL;
|
|
||||||
/* must invalidate that ugly cache */
|
|
||||||
iobuf_ioctl (NULL, 2, 0, (char*)filename);
|
|
||||||
} /* end file creation */
|
|
||||||
|
|
||||||
if(keyring_register_filename (filename, secret, &token))
|
|
||||||
{
|
|
||||||
if (used_resources >= MAX_KEYDB_RESOURCES)
|
|
||||||
rc = GPG_ERR_RESOURCE_LIMIT;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(flags&2)
|
|
||||||
primary_keyring=token;
|
|
||||||
all_resources[used_resources].type = rt;
|
|
||||||
all_resources[used_resources].u.kr = NULL; /* Not used here */
|
|
||||||
all_resources[used_resources].token = token;
|
|
||||||
all_resources[used_resources].secret = secret;
|
|
||||||
used_resources++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* This keyring was already registered, so ignore it.
|
|
||||||
However, we can still mark it as primary even if it was
|
|
||||||
already registered. */
|
|
||||||
if(flags&2)
|
|
||||||
primary_keyring=token;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
log_error ("resource type of `%s' not supported\n", url);
|
|
||||||
rc = GPG_ERR_GENERAL;
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fixme: check directory permissions and print a warning */
|
|
||||||
|
|
||||||
leave:
|
|
||||||
if (rc)
|
|
||||||
log_error ("keyblock resource `%s': %s\n", filename, gpg_strerror (rc));
|
|
||||||
else if (secret)
|
|
||||||
any_secret = 1;
|
|
||||||
else
|
|
||||||
any_public = 1;
|
|
||||||
xfree (filename);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
KEYDB_HANDLE
|
|
||||||
keydb_new (int secret)
|
|
||||||
{
|
|
||||||
KEYDB_HANDLE hd;
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
hd = xcalloc (1,sizeof *hd);
|
|
||||||
hd->found = -1;
|
|
||||||
|
|
||||||
assert (used_resources <= MAX_KEYDB_RESOURCES);
|
|
||||||
for (i=j=0; i < used_resources; i++)
|
|
||||||
{
|
|
||||||
if (!all_resources[i].secret != !secret)
|
|
||||||
continue;
|
|
||||||
switch (all_resources[i].type)
|
|
||||||
{
|
|
||||||
case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
|
|
||||||
break;
|
|
||||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
|
||||||
hd->active[j].type = all_resources[i].type;
|
|
||||||
hd->active[j].token = all_resources[i].token;
|
|
||||||
hd->active[j].secret = all_resources[i].secret;
|
|
||||||
hd->active[j].u.kr = keyring_new (all_resources[i].token, secret);
|
|
||||||
if (!hd->active[j].u.kr) {
|
|
||||||
xfree (hd);
|
|
||||||
return NULL; /* fixme: release all previously allocated handles*/
|
|
||||||
}
|
|
||||||
j++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hd->used = j;
|
|
||||||
|
|
||||||
active_handles++;
|
|
||||||
return hd;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
keydb_release (KEYDB_HANDLE hd)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!hd)
|
|
||||||
return;
|
|
||||||
assert (active_handles > 0);
|
|
||||||
active_handles--;
|
|
||||||
|
|
||||||
unlock_all (hd);
|
|
||||||
for (i=0; i < hd->used; i++) {
|
|
||||||
switch (hd->active[i].type) {
|
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
|
||||||
break;
|
|
||||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
|
||||||
keyring_release (hd->active[i].u.kr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xfree (hd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the name of the current resource. This is function first
|
|
||||||
* looks for the last found found, then for the current search
|
|
||||||
* position, and last returns the first available resource. The
|
|
||||||
* returned string is only valid as long as the handle exists. This
|
|
||||||
* function does only return NULL if no handle is specified, in all
|
|
||||||
* other error cases an empty string is returned.
|
|
||||||
*/
|
|
||||||
const char *
|
|
||||||
keydb_get_resource_name (KEYDB_HANDLE hd)
|
|
||||||
{
|
|
||||||
int idx;
|
|
||||||
const char *s = NULL;
|
|
||||||
|
|
||||||
if (!hd)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if ( hd->found >= 0 && hd->found < hd->used)
|
|
||||||
idx = hd->found;
|
|
||||||
else if ( hd->current >= 0 && hd->current < hd->used)
|
|
||||||
idx = hd->current;
|
|
||||||
else
|
|
||||||
idx = 0;
|
|
||||||
|
|
||||||
switch (hd->active[idx].type) {
|
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
|
||||||
s = NULL;
|
|
||||||
break;
|
|
||||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
|
||||||
s = keyring_get_resource_name (hd->active[idx].u.kr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s? s: "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
lock_all (KEYDB_HANDLE hd)
|
|
||||||
{
|
|
||||||
int i, rc = 0;
|
|
||||||
|
|
||||||
for (i=0; !rc && i < hd->used; i++) {
|
|
||||||
switch (hd->active[i].type) {
|
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
|
||||||
break;
|
|
||||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
|
||||||
rc = keyring_lock (hd->active[i].u.kr, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc) {
|
|
||||||
/* revert the already set locks */
|
|
||||||
for (i--; i >= 0; i--) {
|
|
||||||
switch (hd->active[i].type) {
|
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
|
||||||
break;
|
|
||||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
|
||||||
keyring_lock (hd->active[i].u.kr, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
hd->locked = 1;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
unlock_all (KEYDB_HANDLE hd)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!hd->locked)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i=hd->used-1; i >= 0; i--) {
|
|
||||||
switch (hd->active[i].type) {
|
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
|
||||||
break;
|
|
||||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
|
||||||
keyring_lock (hd->active[i].u.kr, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hd->locked = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the last found keyring. Caller must free it.
|
|
||||||
* The returned keyblock has the kbode flag bit 0 set for the node with
|
|
||||||
* the public key used to locate the keyblock or flag bit 1 set for
|
|
||||||
* the user ID node.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
if (!hd)
|
|
||||||
return GPG_ERR_INV_ARG;
|
|
||||||
|
|
||||||
if ( hd->found < 0 || hd->found >= hd->used)
|
|
||||||
return -1; /* nothing found */
|
|
||||||
|
|
||||||
switch (hd->active[hd->found].type) {
|
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
|
||||||
rc = GPG_ERR_GENERAL; /* oops */
|
|
||||||
break;
|
|
||||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
|
||||||
rc = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* update the current keyblock with KB
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
if (!hd)
|
|
||||||
return GPG_ERR_INV_ARG;
|
|
||||||
|
|
||||||
if ( hd->found < 0 || hd->found >= hd->used)
|
|
||||||
return -1; /* nothing found */
|
|
||||||
|
|
||||||
if( opt.dry_run )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
rc = lock_all (hd);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
switch (hd->active[hd->found].type) {
|
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
|
||||||
rc = GPG_ERR_GENERAL; /* oops */
|
|
||||||
break;
|
|
||||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
|
||||||
rc = keyring_update_keyblock (hd->active[hd->found].u.kr, kb);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
unlock_all (hd);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Insert a new KB into one of the resources.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
|
|
||||||
{
|
|
||||||
int rc = -1;
|
|
||||||
int idx;
|
|
||||||
|
|
||||||
if (!hd)
|
|
||||||
return GPG_ERR_INV_ARG;
|
|
||||||
|
|
||||||
if( opt.dry_run )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if ( hd->found >= 0 && hd->found < hd->used)
|
|
||||||
idx = hd->found;
|
|
||||||
else if ( hd->current >= 0 && hd->current < hd->used)
|
|
||||||
idx = hd->current;
|
|
||||||
else
|
|
||||||
return GPG_ERR_GENERAL;
|
|
||||||
|
|
||||||
rc = lock_all (hd);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
switch (hd->active[idx].type) {
|
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
|
||||||
rc = GPG_ERR_GENERAL; /* oops */
|
|
||||||
break;
|
|
||||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
|
||||||
rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
unlock_all (hd);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The current keyblock will be deleted.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
keydb_delete_keyblock (KEYDB_HANDLE hd)
|
|
||||||
{
|
|
||||||
int rc = -1;
|
|
||||||
|
|
||||||
if (!hd)
|
|
||||||
return GPG_ERR_INV_ARG;
|
|
||||||
|
|
||||||
if ( hd->found < 0 || hd->found >= hd->used)
|
|
||||||
return -1; /* nothing found */
|
|
||||||
|
|
||||||
if( opt.dry_run )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
rc = lock_all (hd);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
switch (hd->active[hd->found].type) {
|
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
|
||||||
rc = GPG_ERR_GENERAL; /* oops */
|
|
||||||
break;
|
|
||||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
|
||||||
rc = keyring_delete_keyblock (hd->active[hd->found].u.kr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
unlock_all (hd);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Locate the default writable key resource, so that the next
|
|
||||||
* operation (which is only relevant for inserts) will be done on this
|
|
||||||
* resource.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (!hd)
|
|
||||||
return GPG_ERR_INV_ARG;
|
|
||||||
|
|
||||||
rc = keydb_search_reset (hd); /* this does reset hd->current */
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
/* If we have a primary set, try that one first */
|
|
||||||
if(primary_keyring)
|
|
||||||
{
|
|
||||||
for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
|
|
||||||
{
|
|
||||||
if(hd->active[hd->current].token==primary_keyring)
|
|
||||||
{
|
|
||||||
if(keyring_is_writable (hd->active[hd->current].token))
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = keydb_search_reset (hd); /* this does reset hd->current */
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
|
|
||||||
{
|
|
||||||
switch (hd->active[hd->current].type)
|
|
||||||
{
|
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
|
||||||
BUG();
|
|
||||||
break;
|
|
||||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
|
||||||
if (keyring_is_writable (hd->active[hd->current].token))
|
|
||||||
return 0; /* found (hd->current is set to it) */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Rebuild the caches of all key resources.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
keydb_rebuild_caches (void)
|
|
||||||
{
|
|
||||||
int i, rc;
|
|
||||||
|
|
||||||
for (i=0; i < used_resources; i++)
|
|
||||||
{
|
|
||||||
if (all_resources[i].secret)
|
|
||||||
continue;
|
|
||||||
switch (all_resources[i].type)
|
|
||||||
{
|
|
||||||
case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
|
|
||||||
break;
|
|
||||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
|
||||||
rc = keyring_rebuild_cache (all_resources[i].token);
|
|
||||||
if (rc)
|
|
||||||
log_error (_("failed to rebuild keyring cache: %s\n"),
|
|
||||||
gpg_strerror (rc));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Start the next search on this handle right at the beginning
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
keydb_search_reset (KEYDB_HANDLE hd)
|
|
||||||
{
|
|
||||||
int i, rc = 0;
|
|
||||||
|
|
||||||
if (!hd)
|
|
||||||
return GPG_ERR_INV_ARG;
|
|
||||||
|
|
||||||
hd->current = 0;
|
|
||||||
hd->found = -1;
|
|
||||||
/* and reset all resources */
|
|
||||||
for (i=0; !rc && i < hd->used; i++) {
|
|
||||||
switch (hd->active[i].type) {
|
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
|
||||||
break;
|
|
||||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
|
||||||
rc = keyring_search_reset (hd->active[i].u.kr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Search through all keydb resources, starting at the current position,
|
|
||||||
* for a keyblock which contains one of the keys described in the DESC array.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
|
|
||||||
size_t ndesc, size_t *descindex)
|
|
||||||
{
|
|
||||||
int rc = -1;
|
|
||||||
|
|
||||||
if (!hd)
|
|
||||||
return GPG_ERR_INV_ARG;
|
|
||||||
|
|
||||||
while (rc == -1 && hd->current >= 0 && hd->current < hd->used) {
|
|
||||||
switch (hd->active[hd->current].type) {
|
|
||||||
case KEYDB_RESOURCE_TYPE_NONE:
|
|
||||||
BUG(); /* we should never see it here */
|
|
||||||
break;
|
|
||||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
|
||||||
rc = keyring_search (hd->active[hd->current].u.kr, desc,
|
|
||||||
ndesc, descindex);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (rc == -1) /* EOF -> switch to next resource */
|
|
||||||
hd->current++;
|
|
||||||
else if (!rc)
|
|
||||||
hd->found = hd->current;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
keydb_search_first (KEYDB_HANDLE hd)
|
|
||||||
{
|
|
||||||
KEYDB_SEARCH_DESC desc;
|
|
||||||
|
|
||||||
memset (&desc, 0, sizeof desc);
|
|
||||||
desc.mode = KEYDB_SEARCH_MODE_FIRST;
|
|
||||||
return keydb_search (hd, &desc, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
keydb_search_next (KEYDB_HANDLE hd)
|
|
||||||
{
|
|
||||||
KEYDB_SEARCH_DESC desc;
|
|
||||||
|
|
||||||
memset (&desc, 0, sizeof desc);
|
|
||||||
desc.mode = KEYDB_SEARCH_MODE_NEXT;
|
|
||||||
return keydb_search (hd, &desc, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
|
|
||||||
{
|
|
||||||
KEYDB_SEARCH_DESC desc;
|
|
||||||
|
|
||||||
memset (&desc, 0, sizeof desc);
|
|
||||||
desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
|
|
||||||
desc.u.kid[0] = kid[0];
|
|
||||||
desc.u.kid[1] = kid[1];
|
|
||||||
return keydb_search (hd, &desc, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
|
|
||||||
{
|
|
||||||
KEYDB_SEARCH_DESC desc;
|
|
||||||
|
|
||||||
memset (&desc, 0, sizeof desc);
|
|
||||||
desc.mode = KEYDB_SEARCH_MODE_FPR;
|
|
||||||
memcpy (desc.u.fpr, fpr, MAX_FINGERPRINT_LEN);
|
|
||||||
return keydb_search (hd, &desc, 1);
|
|
||||||
}
|
|
283
g10/keydb.h
283
g10/keydb.h
@ -1,283 +0,0 @@
|
|||||||
/* keydb.h - Key database
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2003 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_KEYDB_H
|
|
||||||
#define G10_KEYDB_H
|
|
||||||
|
|
||||||
#include "types.h"
|
|
||||||
#include "global.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "cipher.h"
|
|
||||||
|
|
||||||
/* What qualifies as a certification (rather than a signature?) */
|
|
||||||
#define IS_CERT(s) (IS_KEY_SIG(s) || IS_UID_SIG(s) || IS_SUBKEY_SIG(s) \
|
|
||||||
|| IS_KEY_REV(s) || IS_UID_REV(s) || IS_SUBKEY_REV(s))
|
|
||||||
#define IS_SIG(s) (!IS_CERT(s))
|
|
||||||
#define IS_KEY_SIG(s) ((s)->sig_class == 0x1f)
|
|
||||||
#define IS_UID_SIG(s) (((s)->sig_class & ~3) == 0x10)
|
|
||||||
#define IS_SUBKEY_SIG(s) ((s)->sig_class == 0x18)
|
|
||||||
#define IS_KEY_REV(s) ((s)->sig_class == 0x20)
|
|
||||||
#define IS_UID_REV(s) ((s)->sig_class == 0x30)
|
|
||||||
#define IS_SUBKEY_REV(s) ((s)->sig_class == 0x28)
|
|
||||||
|
|
||||||
struct getkey_ctx_s;
|
|
||||||
typedef struct getkey_ctx_s *GETKEY_CTX;
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* A Keyblock is all packets which form an entire certificate;
|
|
||||||
* i.e. the public key, certificate, trust packets, user ids,
|
|
||||||
* signatures, and subkey.
|
|
||||||
*
|
|
||||||
* This structure is also used to bind arbitrary packets together.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct kbnode_struct {
|
|
||||||
KBNODE next;
|
|
||||||
PACKET *pkt;
|
|
||||||
int flag;
|
|
||||||
int private_flag;
|
|
||||||
ulong recno; /* used while updating the trustdb */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define is_deleted_kbnode(a) ((a)->private_flag & 1)
|
|
||||||
#define is_cloned_kbnode(a) ((a)->private_flag & 2)
|
|
||||||
|
|
||||||
|
|
||||||
enum resource_type {
|
|
||||||
rt_UNKNOWN = 0,
|
|
||||||
rt_RING = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* A data structre to hold information about the external position
|
|
||||||
* of a keyblock.
|
|
||||||
*/
|
|
||||||
struct keyblock_pos_struct {
|
|
||||||
int resno; /* resource number */
|
|
||||||
enum resource_type rt;
|
|
||||||
off_t offset; /* position information */
|
|
||||||
unsigned count; /* length of the keyblock in packets */
|
|
||||||
iobuf_t fp; /* used by enum_keyblocks */
|
|
||||||
int secret; /* working on a secret keyring */
|
|
||||||
PACKET *pkt; /* ditto */
|
|
||||||
int valid;
|
|
||||||
};
|
|
||||||
typedef struct keyblock_pos_struct KBPOS;
|
|
||||||
|
|
||||||
/* structure to hold a couple of public key certificates */
|
|
||||||
typedef struct pk_list *PK_LIST;
|
|
||||||
struct pk_list {
|
|
||||||
PK_LIST next;
|
|
||||||
PKT_public_key *pk;
|
|
||||||
int flags; /* flag bit 1==throw_keyid */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* structure to hold a couple of secret key certificates */
|
|
||||||
typedef struct sk_list *SK_LIST;
|
|
||||||
struct sk_list {
|
|
||||||
SK_LIST next;
|
|
||||||
PKT_secret_key *sk;
|
|
||||||
int mark; /* not used */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* structure to collect all information which can be used to
|
|
||||||
* identify a public key */
|
|
||||||
typedef struct pubkey_find_info *PUBKEY_FIND_INFO;
|
|
||||||
struct pubkey_find_info {
|
|
||||||
u32 keyid[2];
|
|
||||||
unsigned nbits;
|
|
||||||
byte pubkey_algo;
|
|
||||||
byte fingerprint[MAX_FINGERPRINT_LEN];
|
|
||||||
char userid[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct keydb_handle *KEYDB_HANDLE;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
KEYDB_SEARCH_MODE_NONE,
|
|
||||||
KEYDB_SEARCH_MODE_EXACT,
|
|
||||||
KEYDB_SEARCH_MODE_SUBSTR,
|
|
||||||
KEYDB_SEARCH_MODE_MAIL,
|
|
||||||
KEYDB_SEARCH_MODE_MAILSUB,
|
|
||||||
KEYDB_SEARCH_MODE_MAILEND,
|
|
||||||
KEYDB_SEARCH_MODE_WORDS,
|
|
||||||
KEYDB_SEARCH_MODE_SHORT_KID,
|
|
||||||
KEYDB_SEARCH_MODE_LONG_KID,
|
|
||||||
KEYDB_SEARCH_MODE_FPR16,
|
|
||||||
KEYDB_SEARCH_MODE_FPR20,
|
|
||||||
KEYDB_SEARCH_MODE_FPR,
|
|
||||||
KEYDB_SEARCH_MODE_FIRST,
|
|
||||||
KEYDB_SEARCH_MODE_NEXT
|
|
||||||
} KeydbSearchMode;
|
|
||||||
|
|
||||||
struct keydb_search_desc {
|
|
||||||
KeydbSearchMode mode;
|
|
||||||
int (*skipfnc)(void *,u32*);
|
|
||||||
void *skipfncvalue;
|
|
||||||
union {
|
|
||||||
const char *name;
|
|
||||||
char fpr[MAX_FINGERPRINT_LEN];
|
|
||||||
u32 kid[2];
|
|
||||||
} u;
|
|
||||||
int exact;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*-- keydb.c --*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Flag 1 == force
|
|
||||||
Flag 2 == default
|
|
||||||
*/
|
|
||||||
int keydb_add_resource (const char *url, int flags, int secret);
|
|
||||||
KEYDB_HANDLE keydb_new (int secret);
|
|
||||||
void keydb_release (KEYDB_HANDLE hd);
|
|
||||||
const char *keydb_get_resource_name (KEYDB_HANDLE hd);
|
|
||||||
int keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb);
|
|
||||||
int keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb);
|
|
||||||
int keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb);
|
|
||||||
int keydb_delete_keyblock (KEYDB_HANDLE hd);
|
|
||||||
int keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved);
|
|
||||||
void keydb_rebuild_caches (void);
|
|
||||||
int keydb_search_reset (KEYDB_HANDLE hd);
|
|
||||||
#define keydb_search(a,b,c) keydb_search2((a),(b),(c),NULL)
|
|
||||||
int keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
|
|
||||||
size_t ndesc, size_t *descindex);
|
|
||||||
int keydb_search_first (KEYDB_HANDLE hd);
|
|
||||||
int keydb_search_next (KEYDB_HANDLE hd);
|
|
||||||
int keydb_search_kid (KEYDB_HANDLE hd, u32 *kid);
|
|
||||||
int keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr);
|
|
||||||
|
|
||||||
|
|
||||||
/*-- pkclist.c --*/
|
|
||||||
void show_revocation_reason( PKT_public_key *pk, int mode );
|
|
||||||
int check_signatures_trust( PKT_signature *sig );
|
|
||||||
void release_pk_list( PK_LIST pk_list );
|
|
||||||
int build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use );
|
|
||||||
int algo_available( preftype_t preftype, int algo, void *hint );
|
|
||||||
int select_algo_from_prefs( PK_LIST pk_list, int preftype,
|
|
||||||
int request, void *hint );
|
|
||||||
int select_mdc_from_pklist (PK_LIST pk_list);
|
|
||||||
|
|
||||||
/*-- skclist.c --*/
|
|
||||||
void release_sk_list( SK_LIST sk_list );
|
|
||||||
int build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list,
|
|
||||||
int unlock, unsigned use );
|
|
||||||
|
|
||||||
/*-- passphrase.h --*/
|
|
||||||
int have_static_passphrase(void);
|
|
||||||
void read_passphrase_from_fd( int fd );
|
|
||||||
void passphrase_clear_cache ( u32 *keyid, int algo );
|
|
||||||
DEK *passphrase_to_dek( u32 *keyid, int pubkey_algo,
|
|
||||||
int cipher_algo, STRING2KEY *s2k, int mode,
|
|
||||||
const char *tryagain_text, int *canceled);
|
|
||||||
void set_next_passphrase( const char *s );
|
|
||||||
char *get_last_passphrase(void);
|
|
||||||
|
|
||||||
/*-- getkey.c --*/
|
|
||||||
int classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc);
|
|
||||||
void cache_public_key( PKT_public_key *pk );
|
|
||||||
void getkey_disable_caches(void);
|
|
||||||
int get_pubkey( PKT_public_key *pk, u32 *keyid );
|
|
||||||
int get_pubkey_fast ( PKT_public_key *pk, u32 *keyid );
|
|
||||||
KBNODE get_pubkeyblock( u32 *keyid );
|
|
||||||
int get_pubkey_byname( PKT_public_key *pk, const char *name,
|
|
||||||
KBNODE *ret_keyblock, KEYDB_HANDLE *ret_kdbhd,
|
|
||||||
int include_disabled );
|
|
||||||
int get_pubkey_bynames( GETKEY_CTX *rx, PKT_public_key *pk,
|
|
||||||
STRLIST names, KBNODE *ret_keyblock );
|
|
||||||
int get_pubkey_next( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock );
|
|
||||||
void get_pubkey_end( GETKEY_CTX ctx );
|
|
||||||
int get_seckey( PKT_secret_key *sk, u32 *keyid );
|
|
||||||
int get_primary_seckey( PKT_secret_key *sk, u32 *keyid );
|
|
||||||
int get_pubkey_byfprint( PKT_public_key *pk, const byte *fprint,
|
|
||||||
size_t fprint_len );
|
|
||||||
int get_pubkey_byfprint_fast (PKT_public_key *pk,
|
|
||||||
const byte *fprint, size_t fprint_len);
|
|
||||||
int get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint,
|
|
||||||
size_t fprint_len );
|
|
||||||
int get_keyblock_bylid( KBNODE *ret_keyblock, ulong lid );
|
|
||||||
int seckey_available( u32 *keyid );
|
|
||||||
int get_seckey_byname( PKT_secret_key *sk, const char *name, int unlock );
|
|
||||||
int get_seckey_bynames( GETKEY_CTX *rx, PKT_secret_key *sk,
|
|
||||||
STRLIST names, KBNODE *ret_keyblock );
|
|
||||||
int get_seckey_byfprint( PKT_secret_key *sk,
|
|
||||||
const byte *fprint, size_t fprint_len);
|
|
||||||
int get_seckey_next( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock );
|
|
||||||
void get_seckey_end( GETKEY_CTX ctx );
|
|
||||||
int enum_secret_keys( void **context, PKT_secret_key *sk,
|
|
||||||
int with_subkeys, int with_spm );
|
|
||||||
void merge_keys_and_selfsig( KBNODE keyblock );
|
|
||||||
char*get_user_id_string( u32 *keyid );
|
|
||||||
char*get_user_id_string_printable( u32 *keyid );
|
|
||||||
char*get_long_user_id_string( u32 *keyid );
|
|
||||||
char*get_user_id( u32 *keyid, size_t *rn );
|
|
||||||
char*get_user_id_printable( u32 *keyid );
|
|
||||||
KEYDB_HANDLE get_ctx_handle(GETKEY_CTX ctx);
|
|
||||||
|
|
||||||
/*-- keyid.c --*/
|
|
||||||
int pubkey_letter( int algo );
|
|
||||||
u32 v3_keyid (gcry_mpi_t a, u32 *ki);
|
|
||||||
u32 keyid_from_sk( PKT_secret_key *sk, u32 *keyid );
|
|
||||||
u32 keyid_from_pk( PKT_public_key *pk, u32 *keyid );
|
|
||||||
u32 keyid_from_sig( PKT_signature *sig, u32 *keyid );
|
|
||||||
u32 keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid );
|
|
||||||
byte *namehash_from_uid(PKT_user_id *uid);
|
|
||||||
unsigned nbits_from_pk( PKT_public_key *pk );
|
|
||||||
unsigned nbits_from_sk( PKT_secret_key *sk );
|
|
||||||
const char *datestr_from_pk( PKT_public_key *pk );
|
|
||||||
const char *datestr_from_sk( PKT_secret_key *sk );
|
|
||||||
const char *datestr_from_sig( PKT_signature *sig );
|
|
||||||
const char *expirestr_from_pk( PKT_public_key *pk );
|
|
||||||
const char *expirestr_from_sk( PKT_secret_key *sk );
|
|
||||||
const char *expirestr_from_sig( PKT_signature *sig );
|
|
||||||
|
|
||||||
const char *colon_strtime (u32 t);
|
|
||||||
const char *colon_datestr_from_pk (PKT_public_key *pk);
|
|
||||||
const char *colon_datestr_from_sk (PKT_secret_key *sk);
|
|
||||||
const char *colon_datestr_from_sig (PKT_signature *sig);
|
|
||||||
const char *colon_expirestr_from_sig (PKT_signature *sig);
|
|
||||||
|
|
||||||
byte *fingerprint_from_sk( PKT_secret_key *sk, byte *buf, size_t *ret_len );
|
|
||||||
byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
|
|
||||||
|
|
||||||
char *serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
|
|
||||||
PKT_secret_key *sk);
|
|
||||||
|
|
||||||
|
|
||||||
/*-- kbnode.c --*/
|
|
||||||
KBNODE new_kbnode( PACKET *pkt );
|
|
||||||
KBNODE clone_kbnode( KBNODE node );
|
|
||||||
void release_kbnode( KBNODE n );
|
|
||||||
void delete_kbnode( KBNODE node );
|
|
||||||
void add_kbnode( KBNODE root, KBNODE node );
|
|
||||||
void insert_kbnode( KBNODE root, KBNODE node, int pkttype );
|
|
||||||
void move_kbnode( KBNODE *root, KBNODE node, KBNODE where );
|
|
||||||
void remove_kbnode( KBNODE *root, KBNODE node );
|
|
||||||
KBNODE find_prev_kbnode( KBNODE root, KBNODE node, int pkttype );
|
|
||||||
KBNODE find_next_kbnode( KBNODE node, int pkttype );
|
|
||||||
KBNODE find_kbnode( KBNODE node, int pkttype );
|
|
||||||
KBNODE walk_kbnode( KBNODE root, KBNODE *context, int all );
|
|
||||||
void clear_kbnode_flags( KBNODE n );
|
|
||||||
int commit_kbnode( KBNODE *root );
|
|
||||||
void dump_kbnode( KBNODE node );
|
|
||||||
|
|
||||||
#endif /*G10_KEYDB_H*/
|
|
3856
g10/keyedit.c
3856
g10/keyedit.c
File diff suppressed because it is too large
Load Diff
2916
g10/keygen.c
2916
g10/keygen.c
File diff suppressed because it is too large
Load Diff
609
g10/keyid.c
609
g10/keyid.c
@ -1,609 +0,0 @@
|
|||||||
/* keyid.c - key ID and fingerprint handling
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2003 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "gpg.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "mpi.h"
|
|
||||||
#include "keydb.h"
|
|
||||||
#include "i18n.h"
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
pubkey_letter( int algo )
|
|
||||||
{
|
|
||||||
switch( algo ) {
|
|
||||||
case PUBKEY_ALGO_RSA: return 'R' ;
|
|
||||||
case PUBKEY_ALGO_RSA_E: return 'r' ;
|
|
||||||
case PUBKEY_ALGO_RSA_S: return 's' ;
|
|
||||||
case PUBKEY_ALGO_ELGAMAL_E: return 'g';
|
|
||||||
case PUBKEY_ALGO_ELGAMAL: return 'G' ;
|
|
||||||
case PUBKEY_ALGO_DSA: return 'D' ;
|
|
||||||
default: return '?';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static gcry_md_hd_t
|
|
||||||
do_fingerprint_md( PKT_public_key *pk )
|
|
||||||
{
|
|
||||||
gcry_md_hd_t md;
|
|
||||||
unsigned int n;
|
|
||||||
unsigned int nn[PUBKEY_MAX_NPKEY];
|
|
||||||
byte *pp[PUBKEY_MAX_NPKEY];
|
|
||||||
int i;
|
|
||||||
int npkey = pubkey_get_npkey( pk->pubkey_algo );
|
|
||||||
|
|
||||||
gcry_md_open (&md, pk->version < 4 ? DIGEST_ALGO_RMD160
|
|
||||||
: DIGEST_ALGO_SHA1, 0);
|
|
||||||
|
|
||||||
n = pk->version < 4 ? 8 : 6;
|
|
||||||
for(i=0; i < npkey; i++ ) {
|
|
||||||
size_t nbytes;
|
|
||||||
|
|
||||||
if (gcry_mpi_print( GCRYMPI_FMT_PGP, NULL, 0, &nbytes, pk->pkey[i] ))
|
|
||||||
BUG ();
|
|
||||||
/* fixme: we should try to allocate a buffer on the stack */
|
|
||||||
pp[i] = xmalloc(nbytes);
|
|
||||||
if (gcry_mpi_print ( GCRYMPI_FMT_PGP, pp[i], nbytes, &nbytes,
|
|
||||||
pk->pkey[i] ))
|
|
||||||
BUG ();
|
|
||||||
nn[i] = nbytes;
|
|
||||||
n += nn[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
gcry_md_putc ( md, 0x99 ); /* ctb */
|
|
||||||
gcry_md_putc ( md, n >> 8 ); /* 2 byte length header */
|
|
||||||
gcry_md_putc ( md, n );
|
|
||||||
if( pk->version < 4 )
|
|
||||||
gcry_md_putc ( md, 3 );
|
|
||||||
else
|
|
||||||
gcry_md_putc ( md, 4 );
|
|
||||||
|
|
||||||
{ u32 a = pk->timestamp;
|
|
||||||
gcry_md_putc ( md, a >> 24 );
|
|
||||||
gcry_md_putc ( md, a >> 16 );
|
|
||||||
gcry_md_putc ( md, a >> 8 );
|
|
||||||
gcry_md_putc ( md, a );
|
|
||||||
}
|
|
||||||
if( pk->version < 4 ) {
|
|
||||||
u16 a;
|
|
||||||
|
|
||||||
if( pk->expiredate )
|
|
||||||
a = (u16)((pk->expiredate - pk->timestamp) / 86400L);
|
|
||||||
else
|
|
||||||
a = 0;
|
|
||||||
gcry_md_putc ( md, a >> 8 );
|
|
||||||
gcry_md_putc ( md, a );
|
|
||||||
}
|
|
||||||
gcry_md_putc ( md, pk->pubkey_algo );
|
|
||||||
for(i=0; i < npkey; i++ ) {
|
|
||||||
gcry_md_write( md, pp[i], nn[i] );
|
|
||||||
xfree (pp[i]);
|
|
||||||
}
|
|
||||||
gcry_md_final ( md );
|
|
||||||
|
|
||||||
return md;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gcry_md_hd_t
|
|
||||||
do_fingerprint_md_sk( PKT_secret_key *sk )
|
|
||||||
{
|
|
||||||
PKT_public_key pk;
|
|
||||||
int npkey = pubkey_get_npkey( sk->pubkey_algo ); /* npkey is correct! */
|
|
||||||
int i;
|
|
||||||
|
|
||||||
pk.pubkey_algo = sk->pubkey_algo;
|
|
||||||
pk.version = sk->version;
|
|
||||||
pk.timestamp = sk->timestamp;
|
|
||||||
pk.expiredate = sk->expiredate;
|
|
||||||
pk.pubkey_algo = sk->pubkey_algo;
|
|
||||||
for( i=0; i < npkey; i++ )
|
|
||||||
pk.pkey[i] = sk->skey[i];
|
|
||||||
return do_fingerprint_md( &pk );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
u32
|
|
||||||
v3_keyid (gcry_mpi_t a, u32 *ki)
|
|
||||||
{
|
|
||||||
byte *buffer;
|
|
||||||
size_t nbytes;
|
|
||||||
|
|
||||||
if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &nbytes, a ))
|
|
||||||
BUG ();
|
|
||||||
/* fixme: allocate it on the stack */
|
|
||||||
buffer = xmalloc (nbytes);
|
|
||||||
if (gcry_mpi_print( GCRYMPI_FMT_USG, buffer, nbytes, NULL, a ))
|
|
||||||
BUG ();
|
|
||||||
if (nbytes < 8) /* oops */
|
|
||||||
ki[0] = ki[1] = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memcpy (ki+0, buffer+nbytes-8, 4);
|
|
||||||
memcpy (ki+1, buffer+nbytes-4, 4);
|
|
||||||
}
|
|
||||||
xfree (buffer);
|
|
||||||
return ki[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Get the keyid from the secret key and put it into keyid
|
|
||||||
* if this is not NULL. Return the 32 low bits of the keyid.
|
|
||||||
*/
|
|
||||||
u32
|
|
||||||
keyid_from_sk( PKT_secret_key *sk, u32 *keyid )
|
|
||||||
{
|
|
||||||
u32 lowbits;
|
|
||||||
u32 dummy_keyid[2];
|
|
||||||
|
|
||||||
if( !keyid )
|
|
||||||
keyid = dummy_keyid;
|
|
||||||
|
|
||||||
if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) {
|
|
||||||
keyid[0] = keyid[1] = 0;
|
|
||||||
lowbits = pubkey_get_npkey(sk->pubkey_algo) ?
|
|
||||||
v3_keyid (sk->skey[0], keyid) : 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const byte *dp;
|
|
||||||
gcry_md_hd_t md;
|
|
||||||
md = do_fingerprint_md_sk(sk);
|
|
||||||
dp = gcry_md_read ( md, 0 );
|
|
||||||
keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
|
|
||||||
keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
|
|
||||||
lowbits = keyid[1];
|
|
||||||
gcry_md_close (md);
|
|
||||||
}
|
|
||||||
|
|
||||||
return lowbits;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Get the keyid from the public key and put it into keyid
|
|
||||||
* if this is not NULL. Return the 32 low bits of the keyid.
|
|
||||||
*/
|
|
||||||
u32
|
|
||||||
keyid_from_pk( PKT_public_key *pk, u32 *keyid )
|
|
||||||
{
|
|
||||||
u32 lowbits;
|
|
||||||
u32 dummy_keyid[2];
|
|
||||||
|
|
||||||
if( !keyid )
|
|
||||||
keyid = dummy_keyid;
|
|
||||||
|
|
||||||
if( pk->keyid[0] || pk->keyid[1] ) {
|
|
||||||
keyid[0] = pk->keyid[0];
|
|
||||||
keyid[1] = pk->keyid[1];
|
|
||||||
lowbits = keyid[1];
|
|
||||||
}
|
|
||||||
else if( pk->version < 4 && is_RSA(pk->pubkey_algo) ) {
|
|
||||||
keyid[0] = keyid[1] = 0;
|
|
||||||
lowbits = pubkey_get_npkey(pk->pubkey_algo) ?
|
|
||||||
v3_keyid (pk->pkey[0], keyid) : 0 ;
|
|
||||||
pk->keyid[0] = keyid[0];
|
|
||||||
pk->keyid[1] = keyid[1];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const byte *dp;
|
|
||||||
gcry_md_hd_t md;
|
|
||||||
md = do_fingerprint_md(pk);
|
|
||||||
dp = gcry_md_read ( md, 0 );
|
|
||||||
keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
|
|
||||||
keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
|
|
||||||
lowbits = keyid[1];
|
|
||||||
gcry_md_close (md);
|
|
||||||
pk->keyid[0] = keyid[0];
|
|
||||||
pk->keyid[1] = keyid[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return lowbits;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Get the keyid from the fingerprint. This function is simple for most
|
|
||||||
* keys, but has to do a keylookup for old stayle keys.
|
|
||||||
*/
|
|
||||||
u32
|
|
||||||
keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid )
|
|
||||||
{
|
|
||||||
u32 dummy_keyid[2];
|
|
||||||
|
|
||||||
if( !keyid )
|
|
||||||
keyid = dummy_keyid;
|
|
||||||
|
|
||||||
if( fprint_len != 20 ) {
|
|
||||||
/* This is special as we have to lookup the key first */
|
|
||||||
PKT_public_key pk;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
memset( &pk, 0, sizeof pk );
|
|
||||||
rc = get_pubkey_byfprint( &pk, fprint, fprint_len );
|
|
||||||
if( rc ) {
|
|
||||||
log_error("Oops: keyid_from_fingerprint: no pubkey\n");
|
|
||||||
keyid[0] = 0;
|
|
||||||
keyid[1] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
keyid_from_pk( &pk, keyid );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const byte *dp = fprint;
|
|
||||||
keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
|
|
||||||
keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
|
|
||||||
}
|
|
||||||
|
|
||||||
return keyid[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
u32
|
|
||||||
keyid_from_sig( PKT_signature *sig, u32 *keyid )
|
|
||||||
{
|
|
||||||
if( keyid ) {
|
|
||||||
keyid[0] = sig->keyid[0];
|
|
||||||
keyid[1] = sig->keyid[1];
|
|
||||||
}
|
|
||||||
return sig->keyid[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
byte *
|
|
||||||
namehash_from_uid(PKT_user_id *uid)
|
|
||||||
{
|
|
||||||
if(uid->namehash==NULL)
|
|
||||||
{
|
|
||||||
uid->namehash=xmalloc (20);
|
|
||||||
|
|
||||||
if(uid->attrib_data)
|
|
||||||
gcry_md_hash_buffer (GCRY_MD_RMD160, uid->namehash,
|
|
||||||
uid->attrib_data,uid->attrib_len);
|
|
||||||
else
|
|
||||||
gcry_md_hash_buffer (GCRY_MD_RMD160, uid->namehash,
|
|
||||||
uid->name,uid->len);
|
|
||||||
}
|
|
||||||
|
|
||||||
return uid->namehash;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* return the number of bits used in the pk
|
|
||||||
*/
|
|
||||||
unsigned
|
|
||||||
nbits_from_pk( PKT_public_key *pk )
|
|
||||||
{
|
|
||||||
return pubkey_nbits( pk->pubkey_algo, pk->pkey );
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* return the number of bits used in the sk
|
|
||||||
*/
|
|
||||||
unsigned
|
|
||||||
nbits_from_sk( PKT_secret_key *sk )
|
|
||||||
{
|
|
||||||
return pubkey_nbits( sk->pubkey_algo, sk->skey );
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
mk_datestr (char *buffer, time_t atime)
|
|
||||||
{
|
|
||||||
struct tm *tp;
|
|
||||||
|
|
||||||
if ( atime < 0 ) /* 32 bit time_t and after 2038-01-19 */
|
|
||||||
strcpy (buffer, "????" "-??" "-??"); /* mark this as invalid */
|
|
||||||
else {
|
|
||||||
tp = gmtime (&atime);
|
|
||||||
sprintf (buffer,"%04d-%02d-%02d",
|
|
||||||
1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
|
|
||||||
}
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* return a string with the creation date of the pk
|
|
||||||
* Note: this is alloced in a static buffer.
|
|
||||||
* Format is: yyyy-mm-dd
|
|
||||||
*/
|
|
||||||
const char *
|
|
||||||
datestr_from_pk( PKT_public_key *pk )
|
|
||||||
{
|
|
||||||
static char buffer[11+5];
|
|
||||||
time_t atime = pk->timestamp;
|
|
||||||
|
|
||||||
return mk_datestr (buffer, atime);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
datestr_from_sk( PKT_secret_key *sk )
|
|
||||||
{
|
|
||||||
static char buffer[11+5];
|
|
||||||
time_t atime = sk->timestamp;
|
|
||||||
|
|
||||||
return mk_datestr (buffer, atime);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
datestr_from_sig( PKT_signature *sig )
|
|
||||||
{
|
|
||||||
static char buffer[11+5];
|
|
||||||
time_t atime = sig->timestamp;
|
|
||||||
|
|
||||||
return mk_datestr (buffer, atime);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
expirestr_from_pk( PKT_public_key *pk )
|
|
||||||
{
|
|
||||||
static char buffer[11+5];
|
|
||||||
time_t atime;
|
|
||||||
|
|
||||||
if( !pk->expiredate )
|
|
||||||
return _("never ");
|
|
||||||
atime = pk->expiredate;
|
|
||||||
return mk_datestr (buffer, atime);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
expirestr_from_sk( PKT_secret_key *sk )
|
|
||||||
{
|
|
||||||
static char buffer[11+5];
|
|
||||||
time_t atime;
|
|
||||||
|
|
||||||
if( !sk->expiredate )
|
|
||||||
return _("never ");
|
|
||||||
atime = sk->expiredate;
|
|
||||||
return mk_datestr (buffer, atime);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
expirestr_from_sig( PKT_signature *sig )
|
|
||||||
{
|
|
||||||
static char buffer[11+5];
|
|
||||||
time_t atime;
|
|
||||||
|
|
||||||
if(!sig->expiredate)
|
|
||||||
return _("never ");
|
|
||||||
atime=sig->expiredate;
|
|
||||||
return mk_datestr (buffer, atime);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
colon_strtime (u32 t)
|
|
||||||
{
|
|
||||||
if (!t)
|
|
||||||
return "";
|
|
||||||
if (opt.fixed_list_mode) {
|
|
||||||
static char buf[15];
|
|
||||||
sprintf (buf, "%lu", (ulong)t);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
return strtimestamp(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
colon_datestr_from_pk (PKT_public_key *pk)
|
|
||||||
{
|
|
||||||
if (opt.fixed_list_mode) {
|
|
||||||
static char buf[15];
|
|
||||||
sprintf (buf, "%lu", (ulong)pk->timestamp);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
return datestr_from_pk (pk);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
colon_datestr_from_sk (PKT_secret_key *sk)
|
|
||||||
{
|
|
||||||
if (opt.fixed_list_mode) {
|
|
||||||
static char buf[15];
|
|
||||||
sprintf (buf, "%lu", (ulong)sk->timestamp);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
return datestr_from_sk (sk);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
colon_datestr_from_sig (PKT_signature *sig)
|
|
||||||
{
|
|
||||||
if (opt.fixed_list_mode) {
|
|
||||||
static char buf[15];
|
|
||||||
sprintf (buf, "%lu", (ulong)sig->timestamp);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
return datestr_from_sig (sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
colon_expirestr_from_sig (PKT_signature *sig)
|
|
||||||
{
|
|
||||||
if(!sig->expiredate)
|
|
||||||
return "";
|
|
||||||
if (opt.fixed_list_mode) {
|
|
||||||
static char buf[15];
|
|
||||||
sprintf (buf, "%lu", (ulong)sig->expiredate);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
return expirestr_from_sig (sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************** .
|
|
||||||
* Return a byte array with the fingerprint for the given PK/SK
|
|
||||||
* The length of the array is returned in ret_len. Caller must free
|
|
||||||
* the array or provide an array of length MAX_FINGERPRINT_LEN.
|
|
||||||
*/
|
|
||||||
|
|
||||||
byte *
|
|
||||||
fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len )
|
|
||||||
{
|
|
||||||
byte *buf;
|
|
||||||
const byte *dp;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if( pk->version < 4 && is_RSA(pk->pubkey_algo) ) {
|
|
||||||
/* RSA in version 3 packets is special */
|
|
||||||
gcry_md_hd_t md;
|
|
||||||
|
|
||||||
gcry_md_open (&md, DIGEST_ALGO_MD5, 0);
|
|
||||||
if( pubkey_get_npkey( pk->pubkey_algo ) > 1 ) {
|
|
||||||
size_t nbytes;
|
|
||||||
|
|
||||||
if (gcry_mpi_print( GCRYMPI_FMT_USG, NULL, 0, &nbytes,
|
|
||||||
pk->pkey[0]))
|
|
||||||
BUG ();
|
|
||||||
/* fixme: allocate it on the stack */
|
|
||||||
buf = xmalloc(nbytes);
|
|
||||||
if (gcry_mpi_print (GCRYMPI_FMT_USG, buf, nbytes, NULL,pk->pkey[0]))
|
|
||||||
BUG ();
|
|
||||||
gcry_md_write (md, buf, nbytes);
|
|
||||||
xfree (buf);
|
|
||||||
if (gcry_mpi_print( GCRYMPI_FMT_USG, NULL, 0, &nbytes, pk->pkey[1]))
|
|
||||||
BUG ();
|
|
||||||
/* fixme: allocate it on the stack */
|
|
||||||
buf = xmalloc(nbytes);
|
|
||||||
if (gcry_mpi_print( GCRYMPI_FMT_USG, buf, nbytes, NULL,pk->pkey[1]))
|
|
||||||
BUG ();
|
|
||||||
gcry_md_write( md, buf, nbytes );
|
|
||||||
xfree(buf);
|
|
||||||
}
|
|
||||||
gcry_md_final (md);
|
|
||||||
if( !array )
|
|
||||||
array = xmalloc ( 16 );
|
|
||||||
len = 16;
|
|
||||||
memcpy(array, gcry_md_read (md, DIGEST_ALGO_MD5), 16 );
|
|
||||||
gcry_md_close (md);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
gcry_md_hd_t md;
|
|
||||||
md = do_fingerprint_md(pk);
|
|
||||||
dp = gcry_md_read ( md, 0 );
|
|
||||||
len = gcry_md_get_algo_dlen (gcry_md_get_algo (md));
|
|
||||||
assert( len <= MAX_FINGERPRINT_LEN );
|
|
||||||
if( !array )
|
|
||||||
array = xmalloc ( len );
|
|
||||||
memcpy(array, dp, len );
|
|
||||||
pk->keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
|
|
||||||
pk->keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
|
|
||||||
gcry_md_close (md);
|
|
||||||
}
|
|
||||||
|
|
||||||
*ret_len = len;
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte *
|
|
||||||
fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len )
|
|
||||||
{
|
|
||||||
byte *buf;
|
|
||||||
const char *dp;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) {
|
|
||||||
/* RSA in version 3 packets is special */
|
|
||||||
gcry_md_hd_t md;
|
|
||||||
|
|
||||||
gcry_md_open (&md, DIGEST_ALGO_MD5, 0);
|
|
||||||
if( pubkey_get_npkey( sk->pubkey_algo ) > 1 ) {
|
|
||||||
size_t nbytes;
|
|
||||||
|
|
||||||
if (gcry_mpi_print( GCRYMPI_FMT_USG, NULL, 0, &nbytes, sk->skey[0]))
|
|
||||||
BUG ();
|
|
||||||
/* fixme: allocate it on the stack */
|
|
||||||
buf = xmalloc(nbytes);
|
|
||||||
if (gcry_mpi_print (GCRYMPI_FMT_USG, buf, nbytes, NULL,sk->skey[0]))
|
|
||||||
BUG ();
|
|
||||||
gcry_md_write (md, buf, nbytes);
|
|
||||||
xfree (buf);
|
|
||||||
if (gcry_mpi_print( GCRYMPI_FMT_USG, NULL, 0, &nbytes, sk->skey[1]))
|
|
||||||
BUG ();
|
|
||||||
/* fixme: allocate it on the stack */
|
|
||||||
buf = xmalloc(nbytes);
|
|
||||||
if (gcry_mpi_print( GCRYMPI_FMT_USG, buf,nbytes, NULL, sk->skey[1]))
|
|
||||||
BUG ();
|
|
||||||
gcry_md_write( md, buf, nbytes );
|
|
||||||
xfree(buf);
|
|
||||||
}
|
|
||||||
gcry_md_final (md);
|
|
||||||
if( !array )
|
|
||||||
array = xmalloc ( 16 );
|
|
||||||
len = 16;
|
|
||||||
memcpy(array, gcry_md_read (md, DIGEST_ALGO_MD5), 16 );
|
|
||||||
gcry_md_close (md);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
gcry_md_hd_t md;
|
|
||||||
|
|
||||||
md = do_fingerprint_md_sk(sk);
|
|
||||||
dp = gcry_md_read ( md, 0 );
|
|
||||||
len = gcry_md_get_algo_dlen (gcry_md_get_algo (md));
|
|
||||||
assert( len <= MAX_FINGERPRINT_LEN );
|
|
||||||
if( !array )
|
|
||||||
array = xmalloc ( len );
|
|
||||||
memcpy(array, dp, len );
|
|
||||||
gcry_md_close (md);
|
|
||||||
}
|
|
||||||
|
|
||||||
*ret_len = len;
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Create a serialno/fpr string from the serial number and the secret
|
|
||||||
* key. caller must free the returned string. There is no error
|
|
||||||
* return. */
|
|
||||||
char *
|
|
||||||
serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
|
|
||||||
PKT_secret_key *sk)
|
|
||||||
{
|
|
||||||
unsigned char fpr[MAX_FINGERPRINT_LEN];
|
|
||||||
size_t fprlen;
|
|
||||||
char *buffer, *p;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
fingerprint_from_sk (sk, fpr, &fprlen);
|
|
||||||
buffer = p= xmalloc (snlen*2 + 1 + fprlen*2 + 1);
|
|
||||||
for (i=0; i < snlen; i++, p+=2)
|
|
||||||
sprintf (p, "%02X", sn[i]);
|
|
||||||
*p++ = '/';
|
|
||||||
for (i=0; i < fprlen; i++, p+=2)
|
|
||||||
sprintf (p, "%02X", fpr[i]);
|
|
||||||
*p = 0;
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
1466
g10/keylist.c
1466
g10/keylist.c
File diff suppressed because it is too large
Load Diff
1588
g10/keyring.c
1588
g10/keyring.c
File diff suppressed because it is too large
Load Diff
@ -1,46 +0,0 @@
|
|||||||
/* keyring.h - Keyring operations
|
|
||||||
* Copyright (C) 2001 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 GPG_KEYRING_H
|
|
||||||
#define GPG_KEYRING_H 1
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct keyring_handle *KEYRING_HANDLE;
|
|
||||||
|
|
||||||
int keyring_register_filename (const char *fname, int secret, void **ptr);
|
|
||||||
int keyring_is_writable (void *token);
|
|
||||||
|
|
||||||
KEYRING_HANDLE keyring_new (void *token, int secret);
|
|
||||||
void keyring_release (KEYRING_HANDLE hd);
|
|
||||||
const char *keyring_get_resource_name (KEYRING_HANDLE hd);
|
|
||||||
int keyring_lock (KEYRING_HANDLE hd, int yes);
|
|
||||||
int keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb);
|
|
||||||
int keyring_update_keyblock (KEYRING_HANDLE hd, KBNODE kb);
|
|
||||||
int keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb);
|
|
||||||
int keyring_locate_writable (KEYRING_HANDLE hd);
|
|
||||||
int keyring_delete_keyblock (KEYRING_HANDLE hd);
|
|
||||||
int keyring_search_reset (KEYRING_HANDLE hd);
|
|
||||||
int keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
|
|
||||||
size_t ndesc, size_t *descindex);
|
|
||||||
int keyring_rebuild_cache (void *);
|
|
||||||
|
|
||||||
#endif /*GPG_KEYRING_H*/
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user